tweb/public/9.254c6de333ff0075d341.chunk.js.map
morethanwords 66a722b74f Build
2021-04-23 22:06:21 +04:00

1 line
1.7 MiB
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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

{"version":3,"sources":["webpack:///./public/recorder.min.js","webpack:///./src/components/button.ts","webpack:///./src/components/inputField.ts","webpack:///./src/components/ripple.ts","webpack:///./src/components/scrollable.ts","webpack:///./src/components/checkboxField.ts","webpack:///./src/components/popups/index.ts","webpack:///./src/helpers/dom/findUpTag.ts","webpack:///./src/lib/mtproto/passwordManager.ts","webpack:///./src/components/passwordInputField.ts","webpack:///./src/components/monkeys/password.ts","webpack:///./src/lib/cropper.ts","webpack:///./src/components/popups/avatar.ts","webpack:///./src/components/appSearch.ts","webpack:///./src/components/inputSearch.ts","webpack:///./src/helpers/listenerSetter.ts","webpack:///./src/components/buttonIcon.ts","webpack:///./src/components/sliderTab.ts","webpack:///./src/components/slider.ts","webpack:///./src/components/avatarEdit.ts","webpack:///./src/components/sidebarLeft/tabs/newGroup.ts","webpack:///./src/components/appMediaPlaybackController.ts","webpack:///./src/helpers/dom/attachGrabListeners.ts","webpack:///./src/components/rangeSelector.ts","webpack:///./src/lib/mediaPlayer.ts","webpack:///./src/components/audio.ts","webpack:///./src/components/divAndCaption.ts","webpack:///./src/components/chat/replyContainer.ts","webpack:///./src/components/groupedLayout.ts","webpack:///./src/components/editPeer.ts","webpack:///./src/components/row.ts","webpack:///./src/components/radioForm.ts","webpack:///./src/helpers/clipboard.ts","webpack:///./src/components/radioField.ts","webpack:///./src/components/toast.ts","webpack:///./src/components/usernameInputField.ts","webpack:///./src/components/popups/peer.ts","webpack:///./src/components/sidebarRight/tabs/groupType.ts","webpack:///./src/helpers/listLoader.ts","webpack:///./src/components/appSelectPeers.ts","webpack:///./src/helpers/dom/findUpAttribute.ts","webpack:///./src/components/popups/pickUser.ts","webpack:///./src/components/sidebarRight/tabs/userPermissions.ts","webpack:///./src/components/sidebarRight/tabs/groupPermissions.ts","webpack:///./src/components/popups/deleteDialog.ts","webpack:///./src/components/sidebarRight/tabs/editGroup.ts","webpack:///./src/components/sidebarRight/tabs/editChannel.ts","webpack:///./src/components/sidebarRight/tabs/editContact.ts","webpack:///./src/components/swipeHandler.ts","webpack:///./src/components/sidebarLeft/tabs/addMembers.ts","webpack:///./src/components/sidebarRight/tabs/sharedMedia.ts","webpack:///./src/components/sidebarRight/index.ts","webpack:///./src/components/sidebarRight/tabs/pollResults.ts","webpack:///./src/components/poll.ts","webpack:///./src/components/wrappers.ts","webpack:///./src/helpers/middleware.ts","webpack:///./src/components/sortedUserList.ts","webpack:///./src/components/appSearchSuper..ts","webpack:///./src/components/buttonMenu.ts","webpack:///./src/components/buttonMenuToggle.ts","webpack:///./src/lib/appManagers/appPrivacyManager.ts","webpack:///./src/components/privacySection.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/phoneNumber.ts","webpack:///./src/lib/appManagers/appStickersManager.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/passwordSet.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/emailConfirmation.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/email.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/hint.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/enterPassword.ts","webpack:///./src/components/sidebarLeft/tabs/2fa/index.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/lastSeen.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/profilePhoto.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/forwardMessages.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/addToGroups.ts","webpack:///./src/components/sidebarLeft/tabs/privacy/calls.ts","webpack:///./src/components/sidebarLeft/tabs/activeSessions.ts","webpack:///./src/components/sidebarLeft/tabs/blockedUsers.ts","webpack:///./src/components/sidebarLeft/tabs/privacyAndSecurity.ts","webpack:///./src/helpers/color.ts","webpack:///./src/helpers/highlightningColor.ts","webpack:///./src/components/colorPicker.ts","webpack:///./src/components/sidebarLeft/tabs/backgroundColor.ts","webpack:///./src/components/sidebarLeft/tabs/background.ts","webpack:///./src/helpers/averageColor.ts","webpack:///./src/components/sidebarLeft/tabs/generalSettings.ts","webpack:///./src/components/sidebarLeft/tabs/editProfile.ts","webpack:///./src/components/sidebarLeft/tabs/includedChats.ts","webpack:///./src/components/sidebarLeft/tabs/editFolder.ts","webpack:///./src/components/sidebarLeft/tabs/chatFolders.ts","webpack:///./src/components/sidebarLeft/tabs/notifications.ts","webpack:///./src/components/sidebarLeft/tabs/language.ts","webpack:///./src/components/sidebarLeft/tabs/settings.ts","webpack:///./src/components/sidebarLeft/tabs/newChannel.ts","webpack:///./src/components/sidebarLeft/tabs/contacts.ts","webpack:///./src/components/sidebarLeft/tabs/archivedTab.ts","webpack:///./src/components/sidebarLeft/index.ts","webpack:///./src/components/chat/bubbleGroups.ts","webpack:///./src/components/popups/datePicker.ts","webpack:///./src/components/popups/forward.ts","webpack:///./src/components/popups/stickers.ts","webpack:///./src/components/stickyIntersector.ts","webpack:///./src/components/chat/replies.ts","webpack:///./src/components/chat/messageRender.ts","webpack:///./src/helpers/dom/getElementByPoint.ts","webpack:///./src/components/chat/bubbles.ts","webpack:///./src/components/popups/deleteMessages.ts","webpack:///./src/components/popups/unpinMessage.ts","webpack:///./src/components/popups/sendNow.ts","webpack:///./src/components/chat/contextMenu.ts","webpack:///./src/components/emoticonsDropdown/tabs/emoji.ts","webpack:///./src/components/gifsMasonry.ts","webpack:///./src/components/emoticonsDropdown/tabs/gifs.ts","webpack:///./src/components/emoticonsDropdown/tabs/stickers.ts","webpack:///./src/lib/appManagers/appInlineBotsManager.ts","webpack:///./src/components/sidebarRight/tabs/gifs.ts","webpack:///./src/components/sidebarRight/tabs/stickers.ts","webpack:///./src/components/emoticonsDropdown/index.ts","webpack:///./src/components/chat/sendContextMenu.ts","webpack:///./src/components/popups/createPoll.ts","webpack:///./src/components/popups/newMedia.ts","webpack:///./src/components/chat/stickersHelper.ts","webpack:///./src/components/popups/schedule.ts","webpack:///./src/components/chat/input.ts","webpack:///./src/components/chat/selection.ts","webpack:///./src/components/chat/pinnedContainer.ts","webpack:///./src/components/chat/audio.ts","webpack:///./src/components/chat/pinnedMessageBorder.ts","webpack:///./src/components/chat/pinnedMessage.ts","webpack:///./src/components/chat/search.ts","webpack:///./src/components/sidebarRight/tabs/search.ts","webpack:///./src/components/chat/topbar.ts","webpack:///./src/components/chat/chat.ts","webpack:///./src/components/chat/markupTooltip.ts","webpack:///./src/components/chat/dragAndDrop.ts","webpack:///./src/lib/appManagers/appImManager.ts","webpack:///./src/components/appMediaViewer.ts","webpack:///./src/helpers/dom/getVisibleRect.ts","webpack:///./src/components/avatar.ts","webpack:///./src/components/dialogsContextMenu.ts","webpack:///./src/lib/appManagers/appDialogsManager.ts","webpack:///./src/components/monkeys/tracking.ts","webpack:///./src/components/codeInputField.ts"],"names":["self","module","exports","e","t","o","i","n","l","call","m","c","d","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","__esModule","create","bind","default","prototype","hasOwnProperty","p","s","AudioContext","webkitAudioContext","isRecordingSupported","Error","this","state","config","assign","bufferLength","encoderApplication","encoderFrameSize","encoderPath","encoderSampleRate","maxFramesPerPage","mediaTrackConstraints","monitorGain","numberOfChannels","recordingGain","resampleQuality","streamPages","reuseWorker","wavBitDepth","encodedSamplePosition","navigator","mediaDevices","getUserMedia","WebAssembly","clearStream","stream","getTracks","forEach","stop","audioContext","closeAudioContext","close","encodeBuffers","getChannelData","encoder","postMessage","command","buffers","initAudioContext","context","initAudioGraph","scriptProcessorNode","createScriptProcessor","connect","destination","onaudioprocess","inputBuffer","monitorGainNode","createGain","setMonitorGain","recordingGainNode","setRecordingGain","initSourceNode","Promise","resolve","audio","then","createMediaStreamSource","loadWorker","Worker","initWorker","streamPage","storePage","recordedPages","totalLength","data","message","samplePosition","page","removeEventListener","finish","addEventListener","originalSampleRate","sampleRate","wavSampleRate","pause","onpause","resume","onresume","gain","setTargetAtTime","currentTime","start","sourceNode","onstart","disconnect","destroyWorker","push","length","ondataavailable","Uint8Array","reduce","set","onstop","Function","window","className","options","button","document","createElement","asDiv","icon","noRipple","rippleSquare","classList","add","onlyMobile","disabled","setAttribute","text","append","init","target","hasAttribute","parentElement","preventDefault","originalEvent","clipboardData","getData","entities","parseEntities","filter","_","wrapRichText","noLinks","wrappingDraft","execCommand","checkAndSetRTL","input","char","HTMLInputElement","innerText","direction","style","InputState","container","maxLength","showLengthOn","Math","round","placeholder","name","plainText","processInput","label","labelText","innerHTML","firstElementChild","observer","MutationObserver","inputFake","onFakeInput","observe","characterData","childList","subtree","animate","wasInputFakeClientHeight","showScrollDebounced","remove","undefined","border","setLabel","labelEl","lastElementChild","showingLength","wasError","contains","inputLength","diff","isError","toggle","select","textContent","labelOptions","scrollHeight","clientHeight","height","setValueSilently","event","Event","bubbles","cancelable","dispatchEvent","fireFakeInput","originalValue","silent","wrapDraftText","Valid","setState","rippleClickId","ripple","elem","callback","onEnd","prepend","querySelector","handler","drawRipple","clientX","clientY","startTime","Date","now","clickId","duration","getComputedStyle","getPropertyValue","replace","elapsedTime","cb","mutate","delay","max","setTimeout","touchStartFired","requestAnimationFrame","rect","getBoundingClientRect","clickX","left","clickY","top","size","sqrt","abs","width","x","y","isRippleUnneeded","includes","tagName","touchEnd","settings","animationsEnabled","touches","once","cancelBubble","stopPropagation","passive","dataset","ScrollableBase","el","logPrefix","onScrollMeasure","isHeavyAnimationInProgress","needCheckAfterAnimation","log","error","Array","from","children","onScroll","capture","cancelAnimationFrame","element","position","margin","maxDistance","forceDirection","forceDuration","axis","Scrollable","onScrollOffset","withPaddingContainer","super","onAdditionalScroll","onScrolledTop","onScrolledBottom","lastScrollTop","lastScrollDirection","loadedAll","bottom","splitUp","scrollTop","checkForTriggers","maxScrollTop","setListeners","elements","padding","offsetHeight","getDistanceToEnd","ScrollableX","splitCount","scrollHorizontally","deltaX","scrollWidth","clientWidth","scrollLeft","deltaY","CheckboxField","restriction","toggleDisability","span","type","id","checked","stateKey","getState","stateValue","stateValues","indexOf","setByKey","textArgs","box","checkSvg","createElementNS","setAttributeNS","use","bg","withRipple","withHover","disable","PopupElement","buttons","header","title","onEscape","hide","back","destroy","onClose","btnClose","overlayIsActive","removeItem","navigationItem","onCloseAfterTimeout","checkAnimations","closable","overlayClosable","onOverlayClick","withConfirm","btnConfirm","body","buttonsDiv","buttonsElements","map","b","isDanger","langKey","langArgs","isCancel","onPop","pushItem","offsetWidth","addCancelButton","find","findUpTag","tag","closest","passwordManager","invokeApi","result","currentHashPromise","newHashPromise","params","password","new_settings","hint","email","currentPassword","computeSRP","newAlgo","new_algo","salt1","randomize","newPassword","all","hashes","new_password_hash","inputCheckPassword","auth","saveApiUser","user","setUserAuth","code","PasswordInputField","passwordVisible","onVisibilityClick","toggleVisible","onVisibilityClickAdditional","autocomplete","stealthy","tabIndex","insertBefore","cloneNode","nextSibling","PasswordMonkey","passwordInputField","needFrame","loadPromise","loadAnimationFromURL","loop","autoplay","noCache","_animation","animation","currentFrame","setSpeed","setDirection","curFrame","play","waitForFirstFrame","originalImage","canvas","cropComponent","cropImage","event_state","cropLeft","cropTop","cropWidth","cropHeight","scaledRatio","draggable","Image","src","overlayColor","appendChild","parentNode","maxWidth","naturalWidth","CROPWIDTH","CROPHEIGHT","updateCropSize","updateCropImage","updateContainer","startMoving","resizing","keyHandler","imgZoom","zoom","PI","right","newWidth","floor","newHeight","w","h","offsetLeft","offsetTop","String","fromCharCode","charCode","container_width","container_height","container_left","container_top","mouse_x","pageX","scrollX","mouse_y","pageY","scrollY","saveEventState","moving","endMoving","currentTouch","complete","onload","crop","getContext","drawImage","removeHandlers","image","cropper","h6","cropContainer","display","file","files","reader","FileReader","contents","show","readAsDataURL","btnSubmit","click","toBlob","blob","darkenCanvas","onCrop","appDownloadManager","upload","postCanvas","ctx","fillStyle","fillRect","clearable","clickable","autonomous","onFound","list","createChatList","nameEl","setListClickListener","childElementCount","setActive","clear","searchInput","searchGroups","onSearch","minMsgId","loadedCount","foundCount","searchPromise","searchTimeout","query","listsContainer","peerId","threadId","scrollable","messages","setVirtualContainer","onChange","reset","searchMore","trim","focus","maxId","getSearch","inputFilter","limit","res","count","history","mid","shift","searchGroup","dialog","dom","addDialogNew","drawStatus","avatarSize","setLastMessage","catch","err","console","prevValue","timeout","onInput","clearTimeout","onClearClick","onClear","inputField","searchIcon","clearBtn","ListenerSetter","listeners","Set","listener","addManual","delete","_listener","slider","destroyable","_constructor","closeBtn","content","addTab","listenerSetter","closeTab","args","selectTab","tabs","removeAll","key","eventListener","cleanup","historyTabIds","canHideFirst","onCloseBtnClick","appNavigationController","findItemByType","navigationType","isNavigation","closingId","pop","onCloseTab","tab","_selectTab","Map","tabsContainer","sidebarEl","querySelectorAll","onOpen","onOpenAfterTimeout","canAnimate","findAndSplice","tabConstructor","preserveTab","removeTabFromHistory","getTab","removeByType","open","clearRect","uploadAvatar","setTitle","avatarEdit","_upload","inputWrapper","groupNameInputField","nextBtn","createChat","userIds","chatId","inputFile","editPhoto","chatsContainer","userId","rippleEnabled","lastMessageSpan","getUserStatusString","appMediaPlaybackController","media","waitingMediaForLoad","onPause","rootScope","broadcast","onEnded","nextMid","currentPeerId","resolveWaitingForLoadMedia","cssText","doc","autoload","storage","volume","playingMedia","paused","loadSiblingsMedia","onError","deferred","supportsStreaming","downloadDoc","handleSafariStreamable","url","promise","safariBuffering","prevMid","backLimit","Boolean","getMessageByPeer","addMedia","willBePlayedMedia","attachGrabListeners","onStart","onMove","onMouseMove","onMouseUp","onMouseDown","onTouchMove","isTouch","onTouchEnd","onTouchStart","step","min","mousedown","events","scrub","seek","setFilled","onScrub","filled","setProgress","stepStr","index","decimals","_removeListeners","percents","offsetX","toFixed","streamable","stopAndScrubTimeout","progressRAF","onLoadedData","onPlay","setLoadProgress","onProgress","filledLoad","setSeekMax","setHandlers","scrubTime","isSafariBuffering","buf","buffered","numRanges","nearestStart","end","removeListeners","lastVolume","video","onFullScreen","webkitFullscreenElement","wrapper","skin","ckin","stylePlayer","controls","progress","muted","finally","initDuration","player","html","buildControls","timeDuration","insertAdjacentHTML","fullScreenButton","timeElapsed","toHHMMSS","volumeDiv","volumeSvg","volumeProgress","setVolume","togglePlay","showControlsTimeout","toggleFullScreen","split","eventName","fullscreenElement","mozFullScreenElement","msFullscreenElement","webkitEnterFullscreen","enterFullscreen","isFullScreen","cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen","msExitFullscreen","requestFullscreen","mozRequestFullScreen","webkitRequestFullscreen","msRequestFullscreen","wrapVoiceMessage","audioEl","webpage","isOut","fromId","myId","isUnread","pFlags","media_unread","out","barHeightMax","mediaSizes","isMobile","svg","timeDiv","waveform","attributes","attribute","valueCount","dataView","DataView","buffer","byteIndex","bitShift","getUint16","decodeWaveform","slice","normValue","wfSize","barCount","maxValue","maxDelta","barX","sumI","bar_value","barWidth","rects","interval","lastIndex","node","clearInterval","setInterval","isNaN","addAudioListener","readMessages","mousemove","MouseEvent","targetTouches","on","mids","HTMLElement","withTime","voiceAsMusic","showSender","attachedHandlers","isRealVoice","isVoice","isOutgoing","is_outgoing","uploading","preloader","durationStr","downloadDiv","onTypeLoad","senderTitle","getSenderToPeerText","subtitle","audioTitle","file_name","audioPerformer","wrapPlainText","formatDate","date","titleAdditionHTML","fontWeight","subtitleDiv","launched","progressLine","lastChild","replaceWith","onPlaying","wrapAudio","audioTimeDiv","onLoad","onTypeDisconnect","getTimeStr","attach","getDownloadPromise","load","download","onClick","construct","setManual","setDownloadFunction","noAutoDownload","willBePlayed","readyState","isConnected","customElements","define","DivAndCaption","fill","wrapReplyDivAndCaption","titleEl","subtitleEl","mediaEl","wrapEmojiText","setMedia","wrapMessageForReply","photo","boxSize","backgroundImage","wrapSticker","div","lazyLoadQueue","chat","group","CHAT_ANIMATION_GROUP","getCacheContext","downloaded","sizes","thumbs","bytes","renderImageFromUrl","getPreviewURLFromThumb","choosePhotoSize","preloadPhoto","getDocumentCachedThumb","isMediaSet","RectPart","minWidth","spacing","maxHeight","ratios","countRatios","proportions","countProportions","averageRatio","maxSizeRatio","layout","layoutTwo","layoutThree","layoutFour","layoutTwoTopBottom","layoutTwoLeftRightEqual","layoutTwoLeftRight","layoutThreeLeftAndOther","layoutThreeTopAndOther","layoutFourTopAndOther","layoutFourLeftAndOther","geometry","sides","minimalWidth","secondWidth","firstWidth","firstHeight","thirdHeight","secondHeight","rightWidth","leftWidth","thirdWidth","h0","w0","w2","w1","h1","h2","ratio","join","cropRatios","attempts","multiHeight","offset","sum","pushAttempt","lineCounts","heights","first","second","third","fourth","optimalAttempt","optimalDiff","attempt","counts","lineCount","totalHeight","minLineHeight","bad1","bad2","line","optimalCounts","optimalHeights","rowCount","row","colCount","lineHeight","col","isChanged","inputFields","isValid","handleChange","avatarElem","doNotEditAvatar","freezed","radioField","checkboxField","subtitleLangKey","havePadding","isToggle","titleRight","noCheckboxSubtitle","titleLangKey","navigationTab","RadioFormFromRows","rows","radios","form","RadioForm","copyTextToClipboard","clipboard","writeText","textArea","removeChild","fallbackCopyTextToClipboard","appStateManager","main","toastEl","toast","checkUsernameDebounced","checkUsername","getValue","Neutral","isUsernameValid","setError","invalidText","head","username","checkUsernamePromise","channel","getChannelInput","available","availableText","takenText","avatarEl","descriptionLangKey","titleLangArgs","descriptionLangArgs","description","fragment","createDocumentFragment","checkboxes","original","nextElementSibling","section","random","privateRow","publicRow","a","privateSection","publicSection","reverse","getChat","linkRow","chatFull","exported_invite","link","format","btnRevoke","getChatInviteLink","caption","noDelimiter","changed","linkInputField","applyBtn","migrateChat","channelId","updateUsername","setOriginalValue","loading","loaded","getPromise","done","loadAllDialogsPromise","loadedAllDialogs","selected","folderId","offsetIndex","loadedWhat","renderedPeerIds","peerType","multiSelect","tempIds","needSwitchList","f","renderResultsFunc","renderResults","peerIds","notRendered","has","topContainer","selectedContainer","selectedScrollable","delimiter","findUpClassName","li","checkbox","cachedContacts","getMoreResults","appendTo","getResultsPromise","onFirstRender","testSelfSearch","dialogs","archived","pageCount","windowH","tempId","getTempId","getConversations","newOffsetIndex","chatRightsAction","canSendToUser","hasRights","renderSaved","getMoreDialogs","contacts","getMoreContacts","getContacts","arr","splice","channelParticipants","getChannelParticipants","q","participants","participant","user_id","u","promises","getConversationsAll","getMoreChannelParticipants","isNonContactUser","containerEl","getChatMembersString","scroll","onlyFirstName","insertAdjacentElement","scrollIntoViewNew","onAnimationEnd","values","Static","selector","getSelected","onSelect","peerTypes","destroyListener","rights","takeOut","banned_rights","editBanned","btnDeleteException","clearChannelParticipantBannedRights","btnDelete","kickFromChannel","v","flags","exceptionText","toggleWith","defaultBannedRights","default_banned_rights","combineParticipantBannedRights","info","mainFlag","until_date","flag","chatPermissions","editChatDefaultBannedRights","addExceptionRow","openPermissions","getChannelParticipant","generateContentElement","setSubtitle","bannedRights","cantWhat","listEl","update","needAdd","new_participant","view_messages","prev_participant","exceptionsCount","setLength","LOAD_COUNT","loader","getDialogType","peerTitleElement","callbackLeave","leave","callbackDelete","flushHistory","descriptionArgs","getChatFull","descriptionInputField","about","editPeer","groupTypeRow","setGroupTypeSubtitle","permissionsRow","setPermissionsLength","acc","editTitle","editAbout","race","removeAttribute","migrateFrom","migrateTo","_init","getChannelFull","nameInputField","deleteChannel","lastNameInputField","getUser","first_name","last_name","notificationsCheckboxField","isTrusted","mutePeer","peer","getPeerId","enabled","isMuted","notify_settings","notificationsRow","isPeerLocalMuted","profileNameDiv","profileSubtitleDiv","addContact","phone","deleteContacts","getEvent","attachGlobalListenerTo","hadMove","xDown","yDown","handleMove","cursor","onReset","handleStart","_e","verifyTouchTarget","xUp","yUp","xDiff","yDiff","onFirstSwipe","onSwipe","skippable","attachToPromise","ret","selectedPeerIds","addInitial","setText","PARALLAX_SUPPORTED","previous","next","loadCount","loadedAllUp","loadedAllDown","items","item","current","unshift","onJump","older","loadPromiseDown","loadPromiseUp","anchor","loadMore","processed","processItem","photoId","avatar","BASE_CLASS","getPhoto","action","img","getPeerPhoto","putAvatar","avatars","gradient","checkScrollTop","cancel","freeze","listLoader","targets","concat","idx","prevTargets","nextTargets","openAvatarViewer","toRight","go","cancelNextClick","lastDiffX","minX","lastX","SCALE","transform","TRANSLATE_TEMPLATE","addIndex","ceil","getUserPhotos","photos","Number","MAX_SAFE_INTEGER","chat_photo","generateFakeAvatarMessage","activeTab","photo_id","setPeerStatus","needClear","bio","getProfileByPeerId","full","getPeer","notifications","setBio","setPeerStatusInterval","setBioTimeout","oldAvatars","setPeer","cleaned","cleanupHTML","setAvatar","getPeerUsername","rPhone","override","getProfile","userFull","rAbout","canSetNext","historiesStorage","newCloseBtn","animatedCloseIcon","transitionContainer","transitionFirstItem","editBtn","transitionLastItem","secondTitle","profile","searchSuper","nav","isSharedMedia","transition","cleanScrollPositions","isAnyGroup","mediaTabs","onChangeTab","mediaTab","btnAddMembers","isChannel","showConfirmation","inviteToChannel","addChatUser","filtered","filterMessagesByType","usedFromHistory","performSearchResult","findIndex","canViewMembers","loadMutex","peerChanged","setQuery","historyStorage","fillProfileElements","isContact","admin_rights","single","justLoad","AppSharedMediaTab","getElementById","to","medium","mobile","toggleSidebar","sharedMediaTab","enable","active","willChange","animationPromise","appSidebarRight","resultsDiv","poll","getPoll","quiz","rQuestion","results","voters","total_voters","roundPercents","hr","answer","answers","answerEl","answerTitle","answerPercents","minHeight","getVotes","option","votesList","votes","vote","meAsSaved","showMore","next_offset","down","lineTotalLength","minIndex","minRemainder","k","remainder","maxRemainder","pollElement","isClosed","closed","performResults","chosenIndexes","prevQuizHint","hideQuizHint","prevQuizHintOnHide","prevQuizHintTimeout","onHide","maxOffset","isQuiz","isRetracted","isPublic","isMultiple","chosingIndexes","sentVote","getTotalLength","pollId","descKey","is_scheduled","public_voters","multiple_choice","multipleSelect","regular","descDiv","typeDiv","avatarsDiv","close_period","close_date","timeLeftDiv","quizTimer","strokeWidth","radius","circumference","circle","period","closeTime","serverTimeOffset","quizInterval","time","timeLeft","color","stroke","strokeDashoffset","strokeDasharray","getResults","answerDivs","svgLines","numberDivs","footerDiv","viewResults","votersCountDiv","isTabExists","sendVoteBtn","sendVotes","setVotersCount","clickHandler","solution","solution_entities","toggleHint","textEl","bubblesContainer","setQuizHint","correctResult","correct","chosen","answerIndex","foundIndex","indexes","sendVotePromise","sendVote","initQuizHint","timeEl","setResults","recent_voters","maxPercents","setLineProgress","getPercentValue","iterate","fullTime","votersCount","multiplier","wrapVideo","boxWidth","boxHeight","withTail","middleware","noInfo","onlyPreview","withoutPreloader","loadPromises","noPlayButton","isAlbumItem","canAutoplay","autoPlay","gifs","videos","spanTime","spanPlay","needPlayButton","mime_type","photoRes","wrapPhoto","thumb","globalVideo","divRound","baseVal","setPeerPromise","onTimeUpdate","onPaused","onFrame","foreignObject","images","getAttributeNS","gotThumb","getThumb","poster","attachMethod","loadFunc","reject","detach","queueId","animationIntersector","addAnimation","render","timestamp","monthShort","withYear","month","getMonth","str","getDate","getFullYear","getHours","getMinutes","wrapDocument","searchContext","audioElement","extSplitted","ext","isArray","toLowerCase","docDiv","docId","icoDiv","imgs","wrapped","fileName","_downloadDiv","getDoc","saveDocFile","noBlur","setAttachmentSize","loadThumbPromise","thumbImage","getStrippedThumbIfNeeded","clipId","defs","clipPathHTML","parseInt","wrapMediaWithTail","cacheContext","needFadeIn","sequentialDom","mutateElement","renderPromise","onlyThumb","emoji","withThumb","stickerType","sticker","loadLottieWorkers","toneIndex","haveThumbCached","stickerCachedThumbs","afterRender","getPathFromPhotoPathSize","webpWorkerController","isWebpSupported","stickerThumbConverted","convert","getThumbURL","json","loadAnimationWorker","animationData","saveLottiePreview","getAnimation","restart","wrapReply","replyContainer","prepareAlbum","widthItem","heightItem","borderTopLeftRadius","borderBottomLeftRadius","borderTopRightRadius","borderBottomRightRadius","forMedia","mediaDiv","wrapAlbum","groupId","attachmentDiv","getMidsByAlbum","getMessage","album","getMiddleware","cleanupObj","clean","_cleanupObj","users","sorted","doTimeout","updateList","good","SORT_INTERVAL","sortedUser","status","getUserStatusForSort","batch","prevTabId","urlsToRevoke","nextRates","loadedChats","firstLoad","logger","monthContainers","mediaTabsMap","asChatList","groupByMonth","hideEmptyTabs","onTransitionStart","overflowY","onTransitionEnd","navScrollableContainer","navScrollable","tabsMenu","menuTab","contentTab","searchGroupMedia","horizontalMenu","tabContent","skipScroll","newMediaTab","fromMediaTab","rect2","inputMessagesFilterPhotoVideo","warn","setSearchContext","copySearchContext","openMedia","useHeavyAnimationCheck","lock","unlockAndRefresh","elemsToAppend","sharedMediaDiv","entity","totalEntities","display_url","sliced","match","matchUrl","same","URL","hostname","rDescription","previewDiv","getAbbreviation","rTitle","sender","method","details","monthContainer","getMonthContainerByTimestamp","afterPerforming","parent","child","inputMessagesFilterEmpty","showMembersCount","participants_count","regExp","RegExp","searchIndexManager","cleanSearchText","titleSpan","formatted","arg","searchContacts","my_results","globalContacts","isShort","minDate","renderRecentSearch","recent","recentSearch","getTopPeers","peers","people","renderParticipants","membersList","setInnerPeer","deleted","loadMembers","loadChats","logStr","used","slicedLength","ids","nextRate","maxDate","next_rate","filters","counters","getSearchCounters","firstMediaTab","counter","membersTab","toLoad","loadType","setHours","setDate","dateTimestamp","getTime","containers","haveTimestamps","isBroadcast","goFirst","revokeObjectURL","empty","newInputFilter","ButtonMenuItem","ButtonMenuToggleHandler","openedMenu","PrivacyType","btnMenu","appPrivacyManager","privacy","rules","inputKey","privacyRules","saveApiUsers","saveApiChats","chats","apiUpdatesManager","processUpdateMessage","inputRule","rule","privacyKey","types","allowPeers","disallowPeers","onRadioChange","captions","captionElement","radioSection","exceptions","Everybody","Nobody","radioRows","Contacts","skipTypes","noExceptions","generateSection","exceptionTexts","exception","_peerIds","newPeerIds","generateStr","splitPeersByType","getPrivacy","getPrivacyRulesDetails","setRadio","chatKey","usersKey","splitted","getUserInput","setPrivacy","phoneSection","storeName","getStickerSetPromises","getStickersByEmoticonsPromises","getStickerSet","access_hash","overwrite","saveStickerSet","stickerset","docs","saveDoc","cachedSet","documents","saveStickers","stickerSet","getStickerSetInput","invokeApiHashable","stickers","getFromCache","pack","packs","emoticon","newSet","setToCache","needSave","installed_date","dcId","thumb_dc_id","isAnimated","animated","location","volume_id","local_id","mimeType","sets","covered","excludeFeatured","exclude_featured","foundSaved","cache","getCache","cover","getAllStickers","allStickers","preloadStickerSets","getRecentStickers","messagesStickers","installedSets","recentStickers","foundStickers","cachedStickersAnimated","cachedStickersStatic","iteratePacks","appStickersManager","getAnimatedEmojiSticker","stickerContainer","inputContent","btnReturn","sliceTabsUntilTab","isFirst","codeInputField","onFill","confirmPasswordEmail","goNext","btnChange","btnResend","cancelPasswordEmail","resendPasswordEmail","onContinueClick","btnContinue","btnSkip","matchEmail","toggleButtons","updateSettings","plainPassword","symbols","onSkipClick","saveHint","monkey","verifyInput","isNew","has_password","IntlElement","getStateInterval","_state","check","btnChangePassword","btnDisablePassword","btnSetRecoveryEmail","has_recovery","btnSetPassword","Session","app_name","app_version","ip","country","date_active","date_created","hash","midtitle","device_model","system_version","authorizations","session","btnTerminate","otherSection","privacyTab","updateActiveSessions","onTerminateClick","menuElement","btnAdd","toggleBlock","bot","blocked","getBlocked","blockedPeerIds","blockedUsersRow","passwordState","twoFactorRow","email_unconfirmed_pattern","activeSessionsRow","setBlockedCount","updateBlocked","rowsByKeys","numberVisibilityRow","lastSeenTimeRow","photoVisibilityRow","callRow","linkAccountRow","groupChatsAddRow","updatePrivacyRow","disallowLength","allowLength","auths","rgbaToHsla","g","hslaToRgba","hue2rgb","hexaToRgba","hexa","rgbaToHexa","rgba","toString","hslaStringToHexa","hsla","alpha","val","endsWith","hslaStringToRgba","highlightningColor","hue","saturation","lightness","onGrabStart","documentElement","boxDragger","onGrabEnd","sliders","hueDragger","hexInputField","rgbInputField","inputs","valid","setColor","rgbRegExp","attachBoxListeners","attachHueListeners","boxRect","pos","saturationHandler","hueRect","hueHandler","updateHexInput","updateRgbInput","hexaToHsla","rgb","boxX","percentY","boxY","percentHue","hueX","updatePicker","rgbaArray","hex","hsl","getCurrentColor","maxX","maxY","posX","posY","lightnessX","lightnessY","_applyColor","updateColorPicker","colorPicker","background","themes","theme","pushToState","applyCurrentTheme","onColorChange","applyColor","grid","backgroundColor","uploadTempId","clicked","onUploadClick","createObjectURL","dc_id","file_reference","docThumb","wallpaper","slug","addNotifyListener","_wallpaper","newDoc","setBackgroundDocument","isUpload","tryAgainOnFail","addWallPaper","onResetClick","defaultTheme","blurCheckboxField","blur","onGridClick","saveToCache","fetch","response","cacheStorage","save","_tempId","onReady","imageUrl","naturalHeight","pixel","pixels","getImageData","pixelsLength","outPixel","Uint8ClampedArray","averageColor","uploadButton","colorButton","resetButton","accountWallpapers","wallpapers","pattern","initialValue","minValue","nameDiv","valueDiv","range","messagesTextSize","chatBackgroundButton","animationsCheckboxField","enterRow","ctrlEnterRow","contactsCheckboxField","privateCheckboxField","groupsCheckboxField","channelsCheckboxField","gifsCheckboxField","videosCheckboxField","suggestCheckboxField","loopCheckboxField","firstNameInputField","bioInputField","getSelf","usernameInputField","setProfileUrl","profileUrlContainer","profileUrlAnchor","href","updateProfile","uploadProfilePhoto","foundInFilters","dialogsByFilters","onSelectChange","confirmBtn","pinned_peers","other","editFolderTab","setFilter","filtersStorage","getDialogFilters","dialogsStorage","getFolder","categoriesSection","exclude_muted","ico","exclude_archived","exclude_read","non_contacts","groups","broadcasts","bots","chatsSection","selectedPeers","include_peers","exclude_peers","addedInitial","_add","originalFilter","deleteFolderButton","updateDialogFilter","bool","menuBtn","generateList","h2Text","categories","includedFlagsContainer","excludedFlagsContainer","include","createDialogFilter","editCheckForChange","loadAnimationPromise","lottieLoader","ul","renderMore","_length","firstTime","onEditOpen","onCreateOpen","filtersRendered","dialogFilter","keys","folder","channels","filterId","orderIndex","createFolderBtn","foldersSection","suggestedSection","onFiltersContainerUpdate","renderFolder","getSuggestedFilters","suggestedFilters","NotifySection","enabledRow","typeText","previewEnabledRow","inputNotifyPeer","getNotifySettings","notifySettings","applySettings","show_previews","mute","showPreviews","inputSettings","mute_until","updateNotifySettings","contactsSignUpRow","soundRow","getContactSignUpNotification","_enabled","setContactSignUpNotification","invokeApiCacheable","lang_pack","languages","language","lang_code","native_name","getLangPack","getCacheLangPack","langPack","logOut","phoneDiv","edit","folders","general","fillElements","channelNameInputField","channelDescriptionInputField","onLengthChange","createChannel","alive","inputSearch","openContacts","_contacts","sort","renderPage","chatList","chatLists","onChatsRegularScroll","onChatsScroll","wasFilterId","onTabChange","_scroll","appSidebarLeft","sidebarHeader","onContactsClick","backBtn","btnArchive","verify","themeCheckboxField","menuButtons","openUsername","toolsBtn","btnMenuFooter","version","newBtnMenu","initSearch","archivedCount","searchContainer","pickedElements","selectedPeerId","selectedMinDate","selectedMaxDate","updatePicked","setProperty","removeProperty","helper","unselectEntity","renderEntity","dates","dateData","getAttribute","peopleContainer","hideNewBtnMenuTimeout","onFocus","clearRecentSearchBtn","detailsMap","newGroupDiff","bubble","updateGroup","fwdFromId","removeBubble","insertObject","foundBubble","foundAtIndex","foundMidOnSameTimestamp","_timestamp","_mid","bubbleGroup","insertIndex","last","initDate","onPick","noButtons","selectedDate","onPrevClick","selectedMonth","setMonth","minMonth","prevBtn","onNextClick","maxMonth","onDateClick","selectedEl","setTimeTitle","setFullYear","controlsDiv","monthTitle","monthsContainer","handleTimeInput","onOverflow","maxString","hoursInputField","minutesInputField","number","setMinutes","popupCenterer","noTitle","timeOptions","minute","hour","sendDate","dateOptions","day","year","IntlDateElement","firstChild","weekday","firstDate","weekStartDate","getDay","renderElement","dayIndex","clonedDate","showOverflowMonths","lines","fromPeerId","initMessagesForward","stickerSetInput","onFooterClick","stickersFooter","toggleStickerSet","onStickersClick","fileId","sendMessageWithDocument","setOnlyOnePlayableGroup","stickersDiv","btn","loadStickerSet","esgSticker","StickyIntersector","observeHeaders","observeElements","headersObserver","IntersectionObserver","entries","entry","targetInfo","boundingClientRect","stickyTarget","rootBoundsInfo","rootBounds","threshold","root","elementsObserver","isIntersecting","sentinel","headerSentinel","addSentinel","unobserve","updated","postKey","replies","leftPart","recent_repliers","getHistoryStorage","channel_id","read_max_id","max_id","readMaxId","textSpan","iconSpan","rippleContainer","subscribeRepliesThread","updateMessage","MessageRender","setTime","bubbleContainer","messageDiv","views","postAuthor","post_author","fwd_from","saved_from_msg_id","forward","edit_date","edit_hide","pinned","timeSpan","renderReplies","isFooter","repliesFooter","setReply","isReplacing","currentReplyDiv","reply_to_mid","replyToPeerId","reply_to","reply_to_peer_id","appPeersManager","originalPeerTitle","originalMessage","appMessagesManager","wrapSingleMessage","needUpdate","replyMid","getPeerTitle","getElementByPoint","verticalSide","horizontalSide","elementFromPoint","IGNORE_ACTIONS","TEST_SCROLL","appUsersManager","appInlineBotsManager","appPhotosManager","appDocsManager","appChatsManager","unreadOut","dateMessages","scrolledDown","isScrollingTimeout","unreaded","loadedTopTimes","loadedBottomTimes","messagesQueuePromise","messagesQueue","messagesQueueOnRender","messagesQueueOnRenderAdditional","firstUnreadBubble","replyFollowHistory","isFirstLoad","onBubblesClick","chatInner","onDatePick","selection","isSelecting","selectedText","toggleByBubble","contactDiv","appImManager","bubbleMid","reply_to_top_id","generateThreadServiceStartMessage","filterMessages","getDiscussionMessage","savedFrom","msgId","isVideoComponentElement","messageId","parents","albumItem","isReplyClick","replyToMid","reply_to_msg_id","topbar","pinnedMessage","setCorrectIndex","requestHistory","setMessageId","setScroll","bubbleGroups","getMessagesStorage","setBubblePosition","scrollingToNewBubble","scrollToNewLastBubble","deleteMessagesByIds","tempMessage","mounted","getMountedBubble","repliesElement","grouped_id","newPoll","renderMessage","updatePosition","deleteEmptyDateGroups","deletedMids","renderedId","renderMaxId","groupedMessagesStorage","obj","highlightBubble","initMessageReply","stickyIntersector","stuck","dateMessage","unlock","refresh","renderNewMessagesByIds","msgIdsByPeer","msgIds","msgs","setUnreadCount","updateUnreadByDialog","unreadedObserver","offline","readed","bubblesMaxId","readHistory","wasHeight","skip","scrolled","part","rAF","onResizeEnd","isScrolledDown","setEndRAF","ResizeObserver","contentRect","realDiff","_part","needScrollTop","onUpdate","getScheduledMessagesStorage","bad","getGroupedBubble","getHistoryTopPromise","getHistoryBottomPromise","getHistory","loadMoreHistory","readOutboxMaxId","permanent","deleteSelectedMids","replyTo","performHistoryResult","dateGroup","scrollToBubble","datasetKey","dateElement","today","bubbleContent","serviceMsg","firstTimestamp","observeStickyHeaderChanges","bubblesToo","attachedUnreadBubble","lastMsgId","samePeer","topMessage","pinnedMessages","isTarget","savedPosition","getChatSavedPosition","getReadMaxIdIfUnread","isJump","apiManager","setQueueId","additionMsgId","maxBubbleId","getBubbleByPoint","oldChatInner","cached","finishPeerChange","lockGroup","unlockGroup","fromUp","followingUnread","mountedByLastMsgId","findNextMountedBubbleByMsgId","onScrolledAllDown","getDialogByPeerId","unread_mark","markDialogUnread","canWrite","canWriteToPeer","setMessagesQueuePromise","queue","setUnreadDelimiter","getDateContainerByMessage","addBubble","multipleRender","albumMustBeRenderedFull","our","isMegagroup","contentWrapper","wasClassNames","classNames","transitionDelay","originalMid","unread","wrapMessageActionTextNew","renderMessagesQueue","is_single","messageMessage","messageMedia","getAlbumText","richText","canHaveTail","emojiEntities","strLength","curr","reply_markup","containerDiv","rowDiv","noLinebreaks","buttonEl","unsafe","verified","wrapUrl","rel","column","callbackButtonClick","messageWithReplies","withReplies","comments","nameContainer","processingWebPage","noAutoDownloadMedia","previewResizer","preview","quote","quoteTextDiv","site_name","titleDiv","textDiv","isSquare","newNameContainer","getMidsByMid","wrapGroupedDocuments","lastContainer","texts","phone_number","wrapPoll","toggleBubbleCheckbox","needName","isForwardFromChannel","from_id","from_name","getPeerColorById","goto","generateTail","isBackLimit","previousScrollHeightMinusTop","needReflowScroll","newScrollTop","getScheduledMessages","realLoadCount","additionMsgIds","isEnd","Both","resultPromise","isAdditionRender","isFirstMessageRender","processResult","historyResult","Top","serviceStartMessageId","threadsServiceMessagesIdsStorage","sup","processPromise","waitPromise","times","targetMid","sortedMids","topIds","middleIds","bottomIds","getServerMessageId","setBubbles","animateAsLadder","lastMsDelay","topRes","middleRes","bottomRes","delays","safeCount","mustBeCount","onConfirm","revoke","deleteScheduledMessages","deleteMessages","titleArgs","canRevoke","unpin","canUnpin","canPinMessage","oneSide","unpinAllMessages","hidePinnedMessages","updatePinnedMessage","buttonText","pinButtonText","sendScheduledMessages","attachTo","appPollsManager","onSendScheduledClick","selectionSendNowBtn","onReplyClick","onEditClick","initMessageEditing","onCopyClick","selectedMids","onCopyAnchorLinkClick","onCopyLinkClick","onPinClick","onUnpinClick","onRetractVote","onStopPoll","stopPoll","onForwardClick","selectionForwardBtn","isTargetAGroupedItem","onSelectClick","onClearSelectionClick","cancelSelection","onDeleteClick","selectionDeleteBtn","onContextMenu","selectedMid","isSelectable","canSelectBubble","isTextSelected","isAnchorTarget","groupedItem","withSelection","notDirect","side","changedTouches","scheduleSending","editMessage","scheduleDate","onMessageSent","messageInput","canEditMessage","canDeleteMessage","loadedURLs","onContentClick","emojiSupported","nodeType","nodeValue","outerHTML","getEmojiFromElement","recentItemsDiv","_emoji","appendEmoji","divs","Emoji","category","emojis","itemsDiv","prev","fromCodePoint","menu","previousElementSibling","emojiScroll","recentEmoji","menuOnClick","spanEmoji","kek","opacity","scrollPromise","processVisibleDiv","getAnimations","checkAnimation","intersector","isVisible","processInvisibleDiv","visible","gifWidth","gifHeight","willUseWidth","gifsContainer","onMediaClick","masonry","EMOTICONSSTICKERGROUP","addLazyLoadQueueRepeat","regularLazyLoadQueue","animatedDivs","checkAnimationContainer","renderSticker","stickerSets","queueCategoryPush","categoryDiv","categoryTitle","superStickerRenderer","recentDiv","categoryPush","downloadOptions","getStickerSetThumbDownloadOptions","needUpscale","menuWrapper","menuScroll","renderStickerSet","inlineResults","botId","geo","getInputPeerById","geo_point","lat","long","stopTime","noErrorBox","botResults","queryId","query_id","qId","savePhoto","msg_id","callbackAnswer","nextOffset","onGifsClick","search","gifsDiv","newSearch","gifBotPeerId","resolveUsername","getInlineResults","setsDiv","countDiv","stickerDiv","renderFeatured","getFeaturedStickers","coveredSets","filterRendered","renderSet","searchStickerSets","tabId","onCloseAfter","onOpenAfter","forceClose","onMouseOut","displayTimeout","toElement","onSelectTabClick","searchButton","deleteBtn","checkRights","tabsEl","tabsElements","canSendStickers","toggleAttribute","canSendGifs","willBeActive","chatInput","lockIntersectionGroup","unlockIntersectionGroup","emojiTab","stickersTab","gifsTab","0","1","2","onmouseout","onmouseover","getVisible","clearVisible","prevId","jumpedTo","which","clearDraft","emoticonsDropdown","sendMenuButtons","onSilentClick","onScheduleClick","sendMenu","openSide","onContextElement","onSubmitClick","send","radioLabel","isEmpty","questions","appendMoreField","correctAnswers","optionInputFields","weakMap","questionInputField","sendSilent","setPeerId","dd","settingsCaption","anonymousCheckboxField","multipleCheckboxField","quizCheckboxField","quizSolutionField","quizElements","quizSolutionCaption","quizHr","quizSolutionContainer","quizSolutionSubtitle","getFilledAnswers","question","quizSolution","validate","force","quizSolutionEntities","inputMediaPoll","getInputMediaPoll","sendOther","replyToMsgId","helperType","clearHelper","questionField","willAttachType","wasInputValue","willAttach","sendFileDetails","onKeyDown","attachFile","itemDiv","isVideo","source","objectURL","videoWidth","videoHeight","thumbBlob","thumbURL","isPhoto","isAudio","onerror","mediaContainer","messageInputField","groupCheckboxField","attachFiles","isMedia","firstType","sendAlbum","sendText","sendFile","foundPhotos","foundVideos","albumsLength","albumContainer","lastEmoticon","stickersContainer","getStickersByEmoticon","ready","getMinDate","appWebPagesManager","appDraftsManager","serverTimeManager","appNotificationsManager","pageEl","btnSend","lastUrl","lastTimeType","replyElements","willSendWebPage","forwardingMids","forwardingFromPeerId","recording","recordCanceled","recordStartTime","lockRedo","canRedoFromHTML","undoHistory","executedHistory","canUndoFromHTML","onCancelRecordClick","recorder","opusDecodeController","setKeepAlive","onEmoticonsOpen","toggleClass","btnToggleEmoticons","onEmoticonsClose","sendMessage","openScheduled","prepareDocumentExecute","undoRedo","needHTML","sameHTMLTimes","currentHTML","handleMarkdownShortcut","formatKeys","getSelection","markupTooltip","showLinkEditor","applyMarkdown","shiftKey","onMessageInput","markdownEntities","richValue","parseMarkdown","mergeEntities","stickersHelper","suggest","checkEmoticon","urlEntities","saveWebPage","setTopInfo","noWebPage","helperFunc","isInputEmpty","setTyping","editMsgId","saveDraftDebounced","updateSendBtn","onBtnSendClick","analyser","createAnalyser","fftSize","frequencyData","frequencyBinCount","getByteFrequencyData","recordRippleEl","ms","recordTimeEl","onHelperCancel","needReturn","onHelperClick","helperWaitingForward","inputContainer","rowsWrapper","tail","fakeRowsWrapper","fakeSelectionWrapper","goDownBtn","onGoDownClick","cancelBtn","dac","newMessageWrapper","inputMessageContainer","goDownUnreadBadge","btnScheduled","attachMenuButtons","fileInput","attachMenu","multiple","btnCancelRecord","btnSendContainer","attachButtonListener","attachMessageInputField","draft","setDraft","saveDraft","touchMouseDown","typedArray","dataBlob","Blob","decode","isVoiceMessage","pinnedControlBtn","fakeContainer","fakePinnedControlBtn","originalChat","pinnedMessageContainer","unread_count","no_webpage","syncDraft","helperToo","clearInput","fromUpdate","getDraft","setInputValue","rMessage","oldInputField","attachMessageInputListeners","ctrlKey","metaKey","readAllHistory","commandsMap","bold","italic","underline","strikethrough","monospace","saveExecuted","executed","haveThisType","isCollapsed","getRangeAt","commonAncestorContainer","matches","setActiveMarkupButton","canSetDraft","clearReply","webPage","forwardMessages","pushRecentSticker","replyFragment","smth","peerTitles","firstMessage","usingFullAlbum","albumMids","getMidsByMessage","callerFunc","toggleSelection","isGroupedBubbleSelected","getBubbleGroupedItems","found","groupContainer","isGroupedSelected","isGroupedMidsSelected","updateBubbleSelection","seen","selecting","canceledSelection","removeManual","documentListenerOptions","isBubbleSelected","hasCheckbox","getCheckboxInputFromBubble","isGrouped","forceSelection","selectionCountEl","cantForward","cantDelete","cantSend","toggleCheckboxes","wasSelecting","borderRadius","forwards","fakeSelectionRect","fakeRowsRect","widthFrom","widthTo","scale","initTranslateX","br","selectionInputWrapper","selectionContainer","btnCancel","isSelected","groupedCheckboxInput","divAndCaption","CLASSNAME_BASE","needClose","isHidden","maxActive","setUtilsWidth","toggleEl","PinnedMessageBorder","drawRect","getClipPath","barHeight","clipPath","path","getBarHeight","getMarkHeight","getMarkTranslateY","getTrackTranslateY","trackHeight","getTrackHeight","markHeight","clipPathId","markTranslateY","trackTranslateY","mark","AnimatedSuper","animateFirst","new","currentIndex","clearRow","DURATION","reflow","clearRows","previousIndex","fromTop","ignorePrevious","setNewRow","previousRow","AnimatedCounter","previousNumber","animatedSuper","decimal","previousDecimalNumber","getRow","EMPTY_INDEX","previousByDecimal","decimalNumber","getDecimal","hideLeft","pinnedMaxMid","pinnedMid","pinnedIndex","wasPinnedIndex","wasPinnedMediaIndex","locked","waitForScrollBottom","loadedBottom","loadedTop","scrollDownListenerSetter","hidden","getCurrentIndexPromise","isStatic","debug","pinnedMessageBorder","animatedSubtitle","animatedMedia","animatedCounter","btnOpen","openPinned","setPinnedMessage","_setPinnedMessage","unsetScrollDownListener","testMid","isNeededMore","getCurrentIndex","LOAD_OFFSET","correctAfter","gotRest","getPinnedMessage","backLimited","offset_id_offset","refreshPosition","setScrollDownListener","handleFollowingPinnedMessage","isLast","setCount","writeTo","writeMediaTo","selectedIndex","selectResult","upBtn","downBtn","foundCountEl","renderedCount","appSearch","onResultsClick","onUpClick","onDownClick","footer","dateBtn","beginSearch","onResize","onChangeScreen","chatAudio","resize","setUtilsRAF","chatUtils","chatInfo","btnBack","person","avatarElement","btnMore","getDeleteButtonText","btnJoin","btnPinned","btnMute","btnSearch","followPinnedMessage","activeScreen","onBtnBackClick","isFirstChat","joinChannel","setMutedState","isTopMessage","hiddenPinnedMessages","byCurrent","wasPeerId","newPinnedMessage","appProfileManager","wasAlreadyUsed","initPeerId","backgroundEl","_item","contextMenu","constructUtils","constructPeerHelpers","constructPinnedHelpers","constructDiscussionHelpers","constructScheduledHelpers","searchTab","setAutoDownloadMedia","setLoadMutex","loadSidebarMedia","autoDownload","setPrefix","getMessageFromStorage","addedListener","waitingForMouseUp","mouseUpCounter","onMouseUpSingle","resetSelection","savedRange","tools1","tools2","cancelClosening","linkBackButton","linkInput","applyLink","isLinkValid","setTooltipPosition","linkApplyButton","applyDiv","delimiter1","delimiter2","delimiter3","startContainer","removeAllRanges","addRange","hideTimeout","nodes","currentMarkups","activeButtons","getActiveMarkupButton","isLinkToggle","bodyRect","selectionRect","inputRect","selectionTop","sizesRect","containerRect","isFirstShow","setMouseUpEvent","activeElement","onDragOver","onDragLeave","onDrop","outlineWrapper","dropIcon","dropHeader","dropSubtitle","sizeX","sizeY","FOCUS_EVENT_NAME","columnEl","updateStatusInterval","backgroundPromises","onHashChange","decodeURIComponent","postId","post","generateMessageId","setSettings","chatsSelectTabDebounced","setLoop","onDocumentPaste","attachType","canDrag","DragEvent","_types","dataTransfer","idle","isIDLE","updateStatus","createNewChat","chatsSelectTab","saveChatPosition","sessionStorage","broadcastEvent","STATE_INIT","getBackground","setBackground","getFile","chatPositions","themeColor","hslaStringToHex","themeColorElem","backgroundUrl","applyHighlightningColor","setCurrentBackground","prevTab","prevIdx","goodMid","renderNewMessages","deleteDeletedMessages","attachDragAndDropListeners","handleSelection","drops","mount","isFiles","foundMedia","foundDocuments","dropsContainer","drop","setPath","transitionTime","setUserStatus","fromIndex","justReturn","spliced","chatIndex","spliceChats","existingIndex","setType","dot","isBot","typings","typingsInPeer","typing","langPackKeys","private","multi","mapa","langPackKey","typingElement","getTypingElement","descriptionElement","getPeerTyping","useWhitespace","typingContainer","getPeerStatus","topButtons","author","preloaderStreamable","lastTarget","isFirstOpen","loadMediaPromiseUp","loadMediaPromiseDown","loadedAllMediaUp","loadedAllMediaDown","needLoadMore","setMoverAnimationPromise","highlightSwitchersTimeout","wholeDiv","mover","MEDIA_VIEWER_CLASSNAME","overlaysDiv","mainDiv","setNewMover","onDownloadClick","setMoverPromise","windowW","evt","btnMenuToggle","setMoverToTarget","closing","fromRight","removeCenterFromMover","wasActive","realParent","SVGImageElement","SVGForeignObjectElement","needOpacity","visibleRect","overflowElement","overflowRect","overflowTop","overflowBottom","sticky","overflow","vertical","horizontal","visualViewport","windowHeight","innerWidth","innerHeight","getVisibleRect","aspecter","HTMLImageElement","HTMLVideoElement","setFullAspect","scaleX","scaleY","brSplitted","SVGSVGElement","sizeTailPath","mediaElement","newClipId","newSvg","SVGUseElement","sX","sY","proportion","upscale","_br","toLeft","newTransform","p1","newMover","timeStr","dateStr","oldAvatar","replaceChild","setAuthorInfo","useContainerAsTarget","loadMoreMedia","moveTheMover","mainColumns","thumbPromise","moverVideo","canPlayThrough","createPlayer","overlay","HAVE_FUTURE_DATA","attachCanPlay","networkState","NETWORK_LOADING","isntEnoughData","updateMediaSource","cancellablePromise","attachPromise","haveImage","currentMessageId","onAuthorClick","savePhotoFile","incrementMessageId","getMediaFromMessage","setBtnMenuToggle","_openMedia","setCaption","currentPhotoId","onAvatarUpdate","removeFromAvatarsCache","getFullPhoto","getTarget","hadMessage","isDialog","oldValue","newValue","getPeerMigratedTo","peerTitle","putPhoto","onArchiveClick","selectedId","editPeerFolders","folder_id","toggleDialogPin","onUnmuteClick","onMuteClick","onUnreadClick","top_message","currentText","connecting","updating","setConnectionStatus","baseDcId","setFirstConnectionTimeout","connectionStatus","online","forceGetDifference","setStatusText","statusEl","statusPreloader","CHANGE_STATE_DELAY","setStateTimeout","statusContainer","constructContainer","doms","menuScrollContainer","lastActiveElements","loadDialogsPromise","loadDialogs","sliceTimeout","rectContainer","rectTarget","firstY","lastY","firstElement","lastElement","elementOverflow","firstIndex","sliceFromStart","sliceFromEnd","onChatsScrollTop","archivedChatList","chatsPreloader","allUnreadCount","bottomPart","addFilter","getDialogDom","validateForFilter","setFiltersUnreadCount","updateDialog","setUnreadMessages","order","containerToAppend","renderedFilter","unsetTyping","foldersScrollable","getNotifyPeerTypeSettings","getAllDrafts","addMissedDialogs","allDialogsLoaded","wasLoaded","accumulateArchivedUnread","updatesState","syncLoading","refreshConversations","topOffset","getOffset","bottomOffset","isDialogMustBeInViewport","reorderDialogs","unreadSpan","mutedCount","notMutedCount","setFilterUnreadCount","_peerId","showFiltersTimeout","needIndex","getConversationPromise","withContext","openInner","lastActiveListElement","setPeerFunc","sameElement","reorderDialogsTimeout","currentOrder","peerIdByIndex","lastMessage","highlightWord","draftMessage","lastTimeSpan","senderBold","statusSpan","unreadMessagesSpan","isPinned","accumulateArchivedTimeout","addDialog","_dialog","originalDialog","getOutputPeer","testDialogForFilter","captionDiv","titleSpanContainer","generateVerifiedIcon","titleP","rightSpan","messageP","use2","appDialogsManager","TrackingMonkey","playAnimation","frame","idleAnimation","CodeInputField","lastLength"],"mappings":"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","file":"9.254c6de333ff0075d341.chunk.js","sourcesContent":["!function(e,t){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define([],t):\"object\"==typeof exports?exports.Recorder=t():e.Recorder=t()}(\"undefined\"!=typeof self?self:this,(function(){return function(e){var t={};function o(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}return o.m=e,o.c=t,o.d=function(e,t,i){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},o.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&\"object\"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,\"default\",{enumerable:!0,value:e}),2&t&&\"string\"!=typeof e)for(var n in e)o.d(i,n,function(t){return e[t]}.bind(null,n));return i},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,\"a\",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p=\"\",o(o.s=0)}([function(e,t,o){\"use strict\";(function(t){var o=t.AudioContext||t.webkitAudioContext,i=function(e){if(!i.isRecordingSupported())throw new Error(\"Recording is not supported in this browser\");e||(e={}),this.state=\"inactive\",this.config=Object.assign({bufferLength:4096,encoderApplication:2049,encoderFrameSize:20,encoderPath:\"encoderWorker.min.js\",encoderSampleRate:48e3,maxFramesPerPage:40,mediaTrackConstraints:!0,monitorGain:0,numberOfChannels:1,recordingGain:1,resampleQuality:3,streamPages:!1,reuseWorker:!1,wavBitDepth:16},e),this.encodedSamplePosition=0};i.isRecordingSupported=function(){return o&&t.navigator&&t.navigator.mediaDevices&&t.navigator.mediaDevices.getUserMedia&&t.WebAssembly},i.prototype.clearStream=function(){this.stream&&(this.stream.getTracks?this.stream.getTracks().forEach((function(e){e.stop()})):this.stream.stop(),delete this.stream),this.audioContext&&this.closeAudioContext&&(this.audioContext.close(),delete this.audioContext)},i.prototype.encodeBuffers=function(e){if(\"recording\"===this.state){for(var t=[],o=0;o<e.numberOfChannels;o++)t[o]=e.getChannelData(o);this.encoder.postMessage({command:\"encode\",buffers:t})}},i.prototype.initAudioContext=function(e){return e&&e.context?(this.audioContext=e.context,this.closeAudioContext=!1):(this.audioContext=new o,this.closeAudioContext=!0),this.audioContext},i.prototype.initAudioGraph=function(){this.encodeBuffers=function(){delete this.encodeBuffers},this.scriptProcessorNode=this.audioContext.createScriptProcessor(this.config.bufferLength,this.config.numberOfChannels,this.config.numberOfChannels),this.scriptProcessorNode.connect(this.audioContext.destination),this.scriptProcessorNode.onaudioprocess=e=>{this.encodeBuffers(e.inputBuffer)},this.monitorGainNode=this.audioContext.createGain(),this.setMonitorGain(this.config.monitorGain),this.monitorGainNode.connect(this.audioContext.destination),this.recordingGainNode=this.audioContext.createGain(),this.setRecordingGain(this.config.recordingGain),this.recordingGainNode.connect(this.scriptProcessorNode)},i.prototype.initSourceNode=function(e){return e&&e.context?t.Promise.resolve(e):t.navigator.mediaDevices.getUserMedia({audio:this.config.mediaTrackConstraints}).then(e=>(this.stream=e,this.audioContext.createMediaStreamSource(e)))},i.prototype.loadWorker=function(){this.encoder||(this.encoder=new t.Worker(this.config.encoderPath))},i.prototype.initWorker=function(){var e=(this.config.streamPages?this.streamPage:this.storePage).bind(this);return this.recordedPages=[],this.totalLength=0,this.loadWorker(),new Promise((t,o)=>{var i=o=>{switch(o.data.message){case\"ready\":t();break;case\"page\":this.encodedSamplePosition=o.data.samplePosition,e(o.data.page);break;case\"done\":this.encoder.removeEventListener(\"message\",i),this.finish()}};this.encoder.addEventListener(\"message\",i),this.encoder.postMessage(Object.assign({command:\"init\",originalSampleRate:this.audioContext.sampleRate,wavSampleRate:this.audioContext.sampleRate},this.config))})},i.prototype.pause=function(e){if(\"recording\"===this.state){if(this.state=\"paused\",e&&this.config.streamPages){var t=this.encoder;return new Promise((e,o)=>{var i=o=>{\"flushed\"===o.data.message&&(t.removeEventListener(\"message\",i),this.onpause(),e())};t.addEventListener(\"message\",i),t.postMessage({command:\"flush\"})})}return this.onpause(),Promise.resolve()}},i.prototype.resume=function(){\"paused\"===this.state&&(this.state=\"recording\",this.onresume())},i.prototype.setRecordingGain=function(e){this.config.recordingGain=e,this.recordingGainNode&&this.audioContext&&this.recordingGainNode.gain.setTargetAtTime(e,this.audioContext.currentTime,.01)},i.prototype.setMonitorGain=function(e){this.config.monitorGain=e,this.monitorGainNode&&this.audioContext&&this.monitorGainNode.gain.setTargetAtTime(e,this.audioContext.currentTime,.01)},i.prototype.start=function(e){if(\"inactive\"===this.state)return this.initAudioContext(e),this.initAudioGraph(),this.encodedSamplePosition=0,this.initWorker().then(()=>this.initSourceNode(e)).then(e=>{this.sourceNode=e,this.state=\"recording\",this.onstart(),this.encoder.postMessage({command:\"getHeaderPages\"}),this.sourceNode.connect(this.monitorGainNode),this.sourceNode.connect(this.recordingGainNode)})},i.prototype.stop=function(){if(\"inactive\"!==this.state){this.state=\"inactive\",this.monitorGainNode.disconnect(),this.scriptProcessorNode.disconnect(),this.recordingGainNode.disconnect(),this.sourceNode.disconnect(),this.clearStream();var e=this.encoder;return new Promise(t=>{var o=i=>{\"done\"===i.data.message&&(e.removeEventListener(\"message\",o),t())};e.addEventListener(\"message\",o),e.postMessage({command:\"done\"}),this.config.reuseWorker||e.postMessage({command:\"close\"})})}return Promise.resolve()},i.prototype.destroyWorker=function(){\"inactive\"===this.state&&this.encoder&&(this.encoder.postMessage({command:\"close\"}),delete this.encoder)},i.prototype.storePage=function(e){this.recordedPages.push(e),this.totalLength+=e.length},i.prototype.streamPage=function(e){this.ondataavailable(e)},i.prototype.finish=function(){if(!this.config.streamPages){var e=new Uint8Array(this.totalLength);this.recordedPages.reduce((function(t,o){return e.set(o,t),t+o.length}),0),this.ondataavailable(e)}this.onstop(),this.config.reuseWorker||delete this.encoder},i.prototype.ondataavailable=function(){},i.prototype.onpause=function(){},i.prototype.onresume=function(){},i.prototype.onstart=function(){},i.prototype.onstop=function(){},e.exports=i}).call(this,o(1))},function(e,t){var o;o=function(){return this}();try{o=o||new Function(\"return this\")()}catch(e){\"object\"==typeof window&&(o=window)}e.exports=o}])}));","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { i18n, LangPackKey } from \"../lib/langPack\";\nimport { ripple } from \"./ripple\";\n\nconst Button = (className: string, options: Partial<{\n noRipple: true, \n onlyMobile: true, \n icon: string, \n rippleSquare: true, \n text: LangPackKey, \n disabled: boolean,\n asDiv: boolean\n}> = {}) => {\n const button: HTMLButtonElement = document.createElement(options.asDiv ? 'div' : 'button') as any;\n button.className = className + (options.icon ? ' tgico-' + options.icon : '');\n\n if(!options.noRipple) {\n if(options.rippleSquare) {\n button.classList.add('rp-square');\n }\n\n ripple(button);\n }\n\n if(options.onlyMobile) {\n button.classList.add('only-handhelds');\n }\n\n if(options.disabled) {\n button.setAttribute('disabled', 'true');\n }\n\n if(options.text) {\n button.append(i18n(options.text));\n }\n\n return button;\n};\n\nexport default Button;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { getRichValue, isInputEmpty } from \"../helpers/dom\";\nimport { debounce } from \"../helpers/schedulers\";\nimport { checkRTL } from \"../helpers/string\";\nimport { i18n, LangPackKey, _i18n } from \"../lib/langPack\";\nimport RichTextProcessor from \"../lib/richtextprocessor\";\n\nlet init = () => {\n document.addEventListener('paste', (e) => {\n if(!(e.target as HTMLElement).hasAttribute('contenteditable') && !(e.target as HTMLElement).parentElement.hasAttribute('contenteditable')) {\n return;\n }\n //console.log('document paste');\n\n //console.log('messageInput paste');\n\n e.preventDefault();\n // @ts-ignore\n let text = (e.originalEvent || e).clipboardData.getData('text/plain');\n\n let entities = RichTextProcessor.parseEntities(text);\n //console.log('messageInput paste', text, entities);\n entities = entities.filter(e => e._ === 'messageEntityEmoji' || e._ === 'messageEntityLinebreak');\n //text = RichTextProcessor.wrapEmojiText(text);\n text = RichTextProcessor.wrapRichText(text, {entities, noLinks: true, wrappingDraft: true});\n\n // console.log('messageInput paste after', text);\n\n // @ts-ignore\n //let html = (e.originalEvent || e).clipboardData.getData('text/html');\n\n // @ts-ignore\n //console.log('paste text', text, );\n window.document.execCommand('insertHTML', false, text);\n });\n\n init = null;\n};\n\nconst checkAndSetRTL = (input: HTMLElement) => {\n //const isEmpty = isInputEmpty(input);\n //console.log('input', isEmpty);\n\n //const char = [...getRichValue(input)][0];\n const char = (input instanceof HTMLInputElement ? input.value : input.innerText)[0];\n let direction = 'ltr';\n if(char && checkRTL(char)) {\n direction = 'rtl';\n }\n\n //console.log('RTL', direction, char);\n\n input.style.direction = direction;\n};\n\nexport enum InputState {\n Neutral = 0,\n Valid = 1,\n Error = 2\n};\n\nexport type InputFieldOptions = {\n placeholder?: LangPackKey, \n label?: LangPackKey, \n labelOptions?: any[],\n labelText?: string,\n name?: string, \n maxLength?: number, \n showLengthOn?: number,\n plainText?: true,\n animate?: true\n};\n\nclass InputField {\n public container: HTMLElement;\n public input: HTMLElement;\n public inputFake: HTMLElement;\n public label: HTMLLabelElement;\n\n public originalValue: string;\n\n //public onLengthChange: (length: number, isOverflow: boolean) => void;\n protected wasInputFakeClientHeight: number;\n protected showScrollDebounced: () => void;\n\n constructor(public options: InputFieldOptions = {}) {\n this.container = document.createElement('div');\n this.container.classList.add('input-field');\n\n if(options.maxLength) {\n options.showLengthOn = Math.round(options.maxLength / 3);\n }\n\n const {placeholder, maxLength, showLengthOn, name, plainText} = options;\n\n let label = options.label || options.labelText;\n\n let input: HTMLElement;\n if(!plainText) {\n if(init) {\n init();\n }\n\n this.container.innerHTML = `\n <div contenteditable=\"true\" class=\"input-field-input\"></div>\n `;\n\n input = this.container.firstElementChild as HTMLElement;\n const observer = new MutationObserver(() => {\n checkAndSetRTL(input);\n\n if(processInput) {\n processInput();\n }\n });\n\n // * because if delete all characters there will br left\n input.addEventListener('input', () => {\n if(isInputEmpty(input)) {\n input.innerHTML = '';\n }\n\n if(this.inputFake) {\n this.inputFake.innerHTML = input.innerHTML;\n this.onFakeInput();\n }\n });\n \n // ! childList for paste first symbol\n observer.observe(input, {characterData: true, childList: true, subtree: true});\n\n if(options.animate) {\n input.classList.add('scrollable', 'scrollable-y');\n this.wasInputFakeClientHeight = 0;\n this.showScrollDebounced = debounce(() => this.input.classList.remove('no-scrollbar'), 150, false, true);\n this.inputFake = document.createElement('div');\n this.inputFake.setAttribute('contenteditable', 'true');\n this.inputFake.className = input.className + ' input-field-input-fake';\n }\n } else {\n this.container.innerHTML = `\n <input type=\"text\" ${name ? `name=\"${name}\"` : ''} autocomplete=\"off\" ${label ? 'required=\"\"' : ''} class=\"input-field-input\">\n `;\n\n input = this.container.firstElementChild as HTMLElement;\n input.addEventListener('input', () => checkAndSetRTL(input));\n }\n\n if(placeholder) {\n _i18n(input, placeholder, undefined, 'placeholder');\n\n if(this.inputFake) {\n _i18n(this.inputFake, placeholder, undefined, 'placeholder');\n }\n }\n\n if(label || placeholder) {\n const border = document.createElement('div');\n border.classList.add('input-field-border');\n this.container.append(border);\n }\n\n if(label) {\n this.label = document.createElement('label');\n this.setLabel();\n this.container.append(this.label);\n }\n\n let processInput: () => void;\n if(maxLength) {\n const labelEl = this.container.lastElementChild as HTMLLabelElement;\n let showingLength = false;\n\n processInput = () => {\n const wasError = input.classList.contains('error');\n // * https://stackoverflow.com/a/54369605 #2 to count emoji as 1 symbol\n const inputLength = plainText ? (input as HTMLInputElement).value.length : [...getRichValue(input)].length;\n const diff = maxLength - inputLength;\n const isError = diff < 0;\n input.classList.toggle('error', isError);\n\n //this.onLengthChange && this.onLengthChange(inputLength, isError);\n\n if(isError || diff <= showLengthOn) {\n this.setLabel();\n labelEl.append(` (${maxLength - inputLength})`);\n if(!showingLength) showingLength = true;\n } else if((wasError && !isError) || showingLength) {\n this.setLabel();\n showingLength = false;\n }\n };\n\n input.addEventListener('input', processInput);\n }\n\n this.input = input;\n }\n\n public select() {\n if((this.input as HTMLInputElement).value) { // * avoid selecting whole empty field on iOS devices\n (this.input as HTMLInputElement).select(); // * select text\n }\n }\n\n public setLabel() {\n this.label.textContent = '';\n if(this.options.labelText) {\n this.label.innerHTML = this.options.labelText;\n } else {\n this.label.append(i18n(this.options.label, this.options.labelOptions));\n }\n }\n\n public onFakeInput() {\n const {scrollHeight, clientHeight} = this.inputFake;\n if(this.wasInputFakeClientHeight && this.wasInputFakeClientHeight !== clientHeight) {\n this.input.classList.add('no-scrollbar'); // ! в сафари может вообще не появиться скролл после анимации, так как ему нужен полный reflow блока с overflow.\n this.showScrollDebounced();\n }\n\n this.wasInputFakeClientHeight = clientHeight;\n this.input.style.height = scrollHeight ? scrollHeight + 'px' : '';\n }\n\n get value() {\n return this.options.plainText ? (this.input as HTMLInputElement).value : getRichValue(this.input);\n //return getRichValue(this.input);\n }\n\n set value(value: string) {\n this.setValueSilently(value, false);\n\n const event = new Event('input', {bubbles: true, cancelable: true});\n this.input.dispatchEvent(event);\n }\n\n public setValueSilently(value: string, fireFakeInput = true) {\n if(this.options.plainText) {\n (this.input as HTMLInputElement).value = value;\n } else {\n this.input.innerHTML = value;\n \n if(this.inputFake) {\n this.inputFake.innerHTML = value;\n\n if(fireFakeInput) {\n this.onFakeInput();\n }\n }\n }\n }\n\n public isValid() {\n return !this.input.classList.contains('error') && this.value !== this.originalValue;\n }\n\n public setOriginalValue(value: InputField['originalValue'] = '', silent = false) {\n this.originalValue = value;\n\n if(!this.options.plainText) {\n value = RichTextProcessor.wrapDraftText(value);\n }\n\n if(silent) {\n this.setValueSilently(value, false); \n } else {\n this.value = value;\n }\n }\n\n public setState(state: InputState, label?: LangPackKey) {\n if(label) {\n this.label.textContent = '';\n this.label.append(i18n(label, this.options.labelOptions));\n }\n\n this.input.classList.toggle('error', !!(state & InputState.Error));\n this.input.classList.toggle('valid', !!(state & InputState.Valid));\n }\n\n public setError(label?: LangPackKey) {\n this.setState(InputState.Error, label);\n }\n}\n\nexport default InputField;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\nimport sequentialDom from \"../helpers/sequentialDom\";\nimport {isTouchSupported} from \"../helpers/touchSupport\";\nimport rootScope from \"../lib/rootScope\";\n\nlet rippleClickId = 0;\nexport function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null, prepend = false) {\n //return;\n if(elem.querySelector('.c-ripple')) return;\n elem.classList.add('rp');\n \n let r = document.createElement('div');\n r.classList.add('c-ripple');\n\n const isSquare = elem.classList.contains('rp-square');\n if(isSquare) {\n r.classList.add('is-square');\n }\n\n elem[prepend ? 'prepend' : 'append'](r);\n\n let handler: () => void;\n //let animationEndPromise: Promise<number>;\n const drawRipple = (clientX: number, clientY: number) => {\n const startTime = Date.now();\n const elem = document.createElement('div');\n\n const clickId = rippleClickId++;\n \n //console.log('ripple drawRipple');\n \n const duration = +window.getComputedStyle(r).getPropertyValue('--ripple-duration').replace('s', '') * 1000;\n //console.log('ripple duration', duration);\n\n handler = () => {\n //handler = () => animationEndPromise.then((duration) => {\n //console.log('ripple animation was:', duration);\n\n //const duration = isSquare || mediaSizes.isMobile ? 200 : 700;\n //return;\n let elapsedTime = Date.now() - startTime;\n const cb = () => {\n //console.log('ripple elapsedTime total pre-remove:', Date.now() - startTime);\n sequentialDom.mutate(() => {\n elem.remove();\n });\n \n if(onEnd) onEnd(clickId);\n };\n if(elapsedTime < duration) {\n let delay = Math.max(duration - elapsedTime, duration / 2);\n setTimeout(() => elem.classList.add('hiding'), Math.max(delay - duration / 2, 0));\n\n setTimeout(cb, delay);\n } else {\n elem.classList.add('hiding');\n setTimeout(cb, duration / 2);\n }\n\n if(!isTouchSupported) {\n window.removeEventListener('contextmenu', handler);\n }\n\n handler = null;\n touchStartFired = false;\n };\n //});\n\n callback && callback(clickId);\n\n /* callback().then((bad) => {\n if(bad) {\n span.remove();\n return;\n } */\n \n //console.log('ripple after promise', Date.now() - startTime);\n //console.log('ripple tooSlow:', tooSlow);\n /* if(tooSlow) {\n span.remove();\n return;\n } */\n\n window.requestAnimationFrame(() => {\n const rect = r.getBoundingClientRect();\n elem.classList.add('c-ripple__circle');\n\n const clickX = clientX - rect.left;\n const clickY = clientY - rect.top;\n\n const radius = Math.sqrt((Math.abs(clickY - rect.height / 2) + rect.height / 2) ** 2 + (Math.abs(clickX - rect.width / 2) + rect.width / 2) ** 2);\n const size = radius;\n\n // center of circle\n const x = clickX - size / 2;\n const y = clickY - size / 2;\n\n //console.log('ripple click', offsetFromCenter, size, clickX, clickY);\n\n elem.style.width = elem.style.height = size + 'px';\n elem.style.left = x + 'px';\n elem.style.top = y + 'px';\n\n // нижний код выполняется с задержкой\n /* animationEndPromise = new Promise((resolve) => {\n span.addEventListener('animationend', () => {\n // 713 -> 700\n resolve(((Date.now() - startTime) / 100 | 0) * 100);\n }, {once: true});\n }); */\n \n // нижний код не всегда включает анимацию ПРИ КЛИКЕ НА ТАЧПАД БЕЗ ТАПТИК ЭНЖИНА\n /* span.style.display = 'none';\n r.append(span);\n duration = +window.getComputedStyle(span).getPropertyValue('animation-duration').replace('s', '') * 1000;\n span.style.display = ''; */\n\n r.append(elem);\n\n //r.classList.add('active');\n //handler();\n });\n //});\n };\n\n const isRippleUnneeded = (e: Event) => e.target !== elem && (\n ['BUTTON', 'A'].includes((e.target as HTMLElement).tagName) \n || findUpClassName(e.target as HTMLElement, 'c-ripple') !== r\n );\n\n // TODO: rename this variable\n let touchStartFired = false;\n if(isTouchSupported) {\n let touchEnd = () => {\n handler && handler();\n };\n \n elem.addEventListener('touchstart', (e) => {\n if(!rootScope.settings.animationsEnabled) {\n return;\n }\n\n //console.log('ripple touchstart', e);\n if(e.touches.length > 1 || touchStartFired || isRippleUnneeded(e)) {\n return;\n }\n \n //console.log('touchstart', e);\n touchStartFired = true;\n \n let {clientX, clientY} = e.touches[0];\n drawRipple(clientX, clientY);\n elem.addEventListener('touchend', touchEnd, {once: true});\n \n window.addEventListener('touchmove', (e) => {\n e.cancelBubble = true;\n e.stopPropagation();\n touchEnd();\n elem.removeEventListener('touchend', touchEnd);\n }, {once: true});\n }, {passive: true});\n } else {\n elem.addEventListener('mousedown', (e) => {\n if(![0, 2].includes(e.button)) { // only left and right buttons\n return;\n }\n\n if(!rootScope.settings.animationsEnabled) {\n return;\n }\n //console.log('ripple mousedown', e, e.target, findUpClassName(e.target as HTMLElement, 'c-ripple') === r);\n\n if(elem.dataset.ripple === '0' || isRippleUnneeded(e)) {\n return;\n } else if(touchStartFired) {\n touchStartFired = false;\n return;\n }\n \n let {clientX, clientY} = e;\n drawRipple(clientX, clientY);\n window.addEventListener('mouseup', handler, {once: true, passive: true});\n window.addEventListener('contextmenu', handler, {once: true, passive: true});\n }, {passive: true});\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { isTouchSupported } from \"../helpers/touchSupport\";\nimport { logger, LogLevels } from \"../lib/logger\";\nimport fastSmoothScroll, { FocusDirection } from \"../helpers/fastSmoothScroll\";\nimport useHeavyAnimationCheck from \"../hooks/useHeavyAnimationCheck\";\nimport { cancelEvent } from \"../helpers/dom\";\n/*\nvar el = $0;\nvar height = 0;\nvar checkUp = false;\n\ndo {\n height += el.scrollHeight;\n} while(el = (checkUp ? el.previousElementSibling : el.nextElementSibling));\nconsole.log(height);\n*/\n\n/*\nArray.from($0.querySelectorAll('.bubble-content')).forEach(_el => {\n\t//_el.style.display = '';\t\n\t//return;\n\n\tlet el = _el.parentElement;\n\tlet height = el.scrollHeight;\n\tlet width = el.scrollWidth;\n\tel.style.width = width + 'px';\n\tel.style.height = height + 'px';\n\t_el.style.display = 'none';\n});\n*/\n\n/* const scrollables: Map<HTMLElement, Scrollable> = new Map();\nconst scrollsIntersector = new IntersectionObserver(entries => {\n for(let entry of entries) {\n const scrollable = scrollables.get(entry.target as HTMLElement);\n\n if(entry.isIntersecting) {\n scrollable.isVisible = true;\n } else {\n scrollable.isVisible = false;\n\n if(!isInDOM(entry.target)) {\n scrollsIntersector.unobserve(scrollable.container);\n scrollables.delete(scrollable.container);\n }\n }\n }\n}); */\n\nexport class ScrollableBase {\n protected log: ReturnType<typeof logger>;\n\n public onScrollMeasure: number = 0;\n protected onScroll: () => void;\n\n public isHeavyAnimationInProgress = false;\n protected needCheckAfterAnimation = false;\n\n constructor(public el: HTMLElement, logPrefix = '', public container: HTMLElement = document.createElement('div')) {\n this.container.classList.add('scrollable');\n\n this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''), LogLevels.error);\n\n if(el) {\n Array.from(el.children).forEach(c => this.container.append(c));\n\n el.append(this.container);\n }\n //this.onScroll();\n }\n\n protected setListeners() {\n window.addEventListener('resize', this.onScroll, {passive: true});\n this.container.addEventListener('scroll', this.onScroll, {passive: true, capture: true});\n\n useHeavyAnimationCheck(() => {\n this.isHeavyAnimationInProgress = true;\n\n if(this.onScrollMeasure) {\n this.needCheckAfterAnimation = true;\n window.cancelAnimationFrame(this.onScrollMeasure);\n }\n }, () => {\n this.isHeavyAnimationInProgress = false;\n\n if(this.needCheckAfterAnimation) {\n this.onScroll();\n this.needCheckAfterAnimation = false;\n }\n });\n }\n\n public append(element: HTMLElement) {\n this.container.append(element);\n }\n\n public scrollIntoViewNew(\n element: HTMLElement,\n position: ScrollLogicalPosition,\n margin?: number,\n maxDistance?: number,\n forceDirection?: FocusDirection,\n forceDuration?: number,\n axis?: 'x' | 'y'\n ) {\n //return Promise.resolve();\n return fastSmoothScroll(this.container, element, position, margin, maxDistance, forceDirection, forceDuration, axis);\n }\n}\n\nexport type SliceSides = 'top' | 'bottom';\nexport type SliceSidesContainer = {[k in SliceSides]: boolean};\n\nexport default class Scrollable extends ScrollableBase {\n public splitUp: HTMLElement;\n public padding: HTMLElement;\n \n public onAdditionalScroll: () => void = null;\n public onScrolledTop: () => void = null;\n public onScrolledBottom: () => void = null;\n \n public lastScrollTop: number = 0;\n public lastScrollDirection: number = 0;\n\n public loadedAll: SliceSidesContainer = {top: true, bottom: false};\n\n constructor(el: HTMLElement, logPrefix = '', public onScrollOffset = 300, withPaddingContainer?: boolean) {\n super(el, logPrefix);\n\n /* if(withPaddingContainer) {\n this.padding = document.createElement('div');\n this.padding.classList.add('scrollable-padding');\n Array.from(this.container.children).forEach(c => this.padding.append(c));\n this.container.append(this.padding);\n } */\n\n this.container.classList.add('scrollable-y');\n this.setListeners();\n }\n\n public setVirtualContainer(el?: HTMLElement) {\n this.splitUp = el;\n this.log('setVirtualContainer:', el, this);\n }\n\n public onScroll = () => {\n //if(this.debug) {\n //this.log('onScroll call', this.onScrollMeasure);\n //}\n\n //return;\n\n if(this.isHeavyAnimationInProgress) {\n if(this.onScrollMeasure) {\n window.cancelAnimationFrame(this.onScrollMeasure);\n }\n\n this.needCheckAfterAnimation = true;\n return;\n }\n\n //if(this.onScrollMeasure || ((this.scrollLocked || (!this.onScrolledTop && !this.onScrolledBottom)) && !this.splitUp && !this.onAdditionalScroll)) return;\n if((!this.onScrolledTop && !this.onScrolledBottom) && !this.splitUp && !this.onAdditionalScroll) return;\n if(this.onScrollMeasure) window.cancelAnimationFrame(this.onScrollMeasure);\n this.onScrollMeasure = window.requestAnimationFrame(() => {\n this.onScrollMeasure = 0;\n\n const scrollTop = this.container.scrollTop;\n this.lastScrollDirection = this.lastScrollTop === scrollTop ? 0 : (this.lastScrollTop < scrollTop ? 1 : -1); // * 1 - bottom, -1 - top\n this.lastScrollTop = scrollTop;\n\n if(this.onAdditionalScroll && this.lastScrollDirection !== 0) {\n this.onAdditionalScroll();\n }\n \n if(this.checkForTriggers) {\n this.checkForTriggers();\n }\n });\n };\n\n public checkForTriggers = () => {\n if((!this.onScrolledTop && !this.onScrolledBottom)) return;\n\n if(this.isHeavyAnimationInProgress) {\n this.onScroll();\n return;\n }\n\n const scrollHeight = this.container.scrollHeight;\n if(!scrollHeight) { // незачем вызывать триггеры если блок пустой или не виден\n return;\n }\n\n const clientHeight = this.container.clientHeight;\n const maxScrollTop = scrollHeight - clientHeight;\n const scrollTop = this.lastScrollTop;\n\n //this.log('checkForTriggers:', scrollTop, maxScrollTop);\n\n if(this.onScrolledTop && scrollTop <= this.onScrollOffset && this.lastScrollDirection <= 0/* && direction === -1 */) {\n this.onScrolledTop();\n }\n\n if(this.onScrolledBottom && (maxScrollTop - scrollTop) <= this.onScrollOffset && this.lastScrollDirection >= 0/* && direction === 1 */) {\n this.onScrolledBottom();\n }\n };\n\n public prepend(...elements: HTMLElement[]) {\n (this.splitUp || this.padding || this.container).prepend(...elements);\n }\n\n public append(...elements: HTMLElement[]) {\n (this.splitUp || this.padding || this.container).append(...elements);\n }\n\n public getDistanceToEnd() {\n return this.scrollHeight - Math.round(this.scrollTop + this.container.offsetHeight);\n }\n\n get isScrolledDown() {\n return this.getDistanceToEnd() <= 1;\n }\n\n set scrollTop(y: number) {\n this.container.scrollTop = y;\n }\n \n get scrollTop() {\n //this.log.trace('get scrollTop');\n return this.container.scrollTop;\n }\n \n get scrollHeight() {\n return this.container.scrollHeight;\n }\n}\n\nexport class ScrollableX extends ScrollableBase {\n constructor(el: HTMLElement, logPrefix = '', public onScrollOffset = 300, public splitCount = 15, public container: HTMLElement = document.createElement('div')) {\n super(el, logPrefix, container);\n\n this.container.classList.add('scrollable-x');\n\n if(!isTouchSupported) {\n const scrollHorizontally = (e: any) => {\n if(!e.deltaX && this.container.scrollWidth > this.container.clientWidth) {\n this.container.scrollLeft += e.deltaY / 4;\n cancelEvent(e);\n }\n };\n \n this.container.addEventListener('wheel', scrollHorizontally, {passive: false});\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appStateManager from \"../lib/appManagers/appStateManager\";\nimport { getDeepProperty } from \"../helpers/object\";\nimport { ripple } from \"./ripple\";\nimport { LangPackKey, _i18n } from \"../lib/langPack\";\n\nexport type CheckboxFieldOptions = {\n text?: LangPackKey,\n textArgs?: any[],\n name?: string, \n round?: boolean, \n toggle?: boolean,\n stateKey?: string,\n stateValues?: any[],\n disabled?: boolean,\n checked?: boolean,\n restriction?: boolean,\n withRipple?: boolean,\n withHover?: boolean,\n};\nexport default class CheckboxField {\n public input: HTMLInputElement;\n public label: HTMLLabelElement;\n public span: HTMLSpanElement;\n\n constructor(options: CheckboxFieldOptions = {}) {\n const label = this.label = document.createElement('label');\n label.classList.add('checkbox-field');\n\n if(options.restriction) {\n label.classList.add('checkbox-field-restriction');\n }\n\n if(options.round) {\n label.classList.add('checkbox-field-round');\n }\n\n if(options.disabled) {\n this.toggleDisability(true);\n }\n\n const input = this.input = document.createElement('input');\n input.type = 'checkbox';\n if(options.name) {\n input.id = 'input-' + options.name;\n }\n\n if(options.checked) {\n input.checked = true;\n }\n\n if(options.stateKey) {\n appStateManager.getState().then(state => {\n const stateValue = getDeepProperty(state, options.stateKey);\n let checked: boolean;\n if(options.stateValues) {\n checked = options.stateValues.indexOf(stateValue) === 1;\n } else {\n checked = stateValue;\n }\n\n this.setValueSilently(checked);\n\n input.addEventListener('change', () => {\n let value: any;\n if(options.stateValues) {\n value = options.stateValues[input.checked ? 1 : 0];\n } else {\n value = input.checked;\n }\n\n appStateManager.setByKey(options.stateKey, value);\n });\n });\n }\n\n let span: HTMLSpanElement;\n if(options.text) {\n span = this.span = document.createElement('span');\n span.classList.add('checkbox-caption');\n _i18n(span, options.text, options.textArgs);\n } else {\n label.classList.add('checkbox-without-caption');\n }\n\n label.append(input);\n\n if(options.toggle) {\n label.classList.add('checkbox-field-toggle');\n\n const toggle = document.createElement('div');\n toggle.classList.add('checkbox-toggle');\n label.append(toggle);\n } else {\n const box = document.createElement('div');\n box.classList.add('checkbox-box');\n \n const checkSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n checkSvg.classList.add('checkbox-box-check');\n checkSvg.setAttributeNS(null, 'viewBox', '0 0 24 24');\n const use = document.createElementNS(\"http://www.w3.org/2000/svg\", \"use\");\n use.setAttributeNS(null, 'href', '#check');\n use.setAttributeNS(null, 'x', '-1');\n checkSvg.append(use);\n \n const bg = document.createElement('div');\n bg.classList.add('checkbox-box-background');\n \n const border = document.createElement('div');\n border.classList.add('checkbox-box-border');\n \n box.append(border, bg, checkSvg);\n \n label.append(box);\n }\n\n if(span) {\n label.append(span);\n }\n\n if(options.withRipple) {\n label.classList.add('checkbox-ripple', 'hover-effect');\n ripple(label, undefined, undefined, true);\n //label.prepend(input);\n } else if(options.withHover) {\n label.classList.add('hover-effect');\n }\n }\n\n get checked() {\n return this.input.checked;\n }\n\n set checked(checked: boolean) {\n this.setValueSilently(checked);\n\n const event = new Event('change', {bubbles: true, cancelable: true});\n this.input.dispatchEvent(event);\n }\n\n public setValueSilently(checked: boolean) {\n this.input.checked = checked;\n }\n\n public toggleDisability(disable: boolean) {\n this.label.classList.toggle('checkbox-disabled', disable);\n return () => this.toggleDisability(!disable);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport rootScope from \"../../lib/rootScope\";\nimport { blurActiveElement } from \"../../helpers/dom\";\nimport { ripple } from \"../ripple\";\nimport animationIntersector from \"../animationIntersector\";\nimport appNavigationController, { NavigationItem } from \"../appNavigationController\";\nimport { i18n, LangPackKey } from \"../../lib/langPack\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\n\nexport type PopupButton = {\n text?: string,\n callback?: () => void,\n langKey?: LangPackKey,\n langArgs?: any[],\n isDanger?: true,\n isCancel?: true\n};\n\nexport type PopupOptions = Partial<{\n closable: true, \n overlayClosable: true, \n withConfirm: LangPackKey | true, \n body: true\n}>;\n\nexport default class PopupElement {\n protected element = document.createElement('div');\n protected container = document.createElement('div');\n protected header = document.createElement('div');\n protected title = document.createElement('div');\n protected btnClose: HTMLElement;\n protected btnConfirm: HTMLElement;\n protected body: HTMLElement;\n\n protected onClose: () => void;\n protected onCloseAfterTimeout: () => void;\n protected onEscape: () => boolean = () => true;\n\n protected navigationItem: NavigationItem;\n\n constructor(className: string, buttons?: Array<PopupButton>, options: PopupOptions = {}) {\n this.element.classList.add('popup');\n this.element.className = 'popup' + (className ? ' ' + className : '');\n this.container.classList.add('popup-container', 'z-depth-1');\n\n this.header.classList.add('popup-header');\n this.title.classList.add('popup-title');\n\n this.header.append(this.title);\n\n if(options.closable) {\n this.btnClose = document.createElement('span');\n this.btnClose.classList.add('btn-icon', 'popup-close', 'tgico-close');\n //ripple(this.closeBtn);\n this.header.prepend(this.btnClose);\n\n this.btnClose.addEventListener('click', this.hide, {once: true});\n }\n\n if(options.overlayClosable) {\n const onOverlayClick = (e: MouseEvent) => {\n if(!findUpClassName(e.target, 'popup-container')) {\n this.hide();\n this.element.removeEventListener('click', onOverlayClick);\n }\n };\n \n this.element.addEventListener('click', onOverlayClick);\n }\n\n if(options.withConfirm) {\n this.btnConfirm = document.createElement('button');\n this.btnConfirm.classList.add('btn-primary', 'btn-color-primary');\n if(options.withConfirm !== true) {\n this.btnConfirm.append(i18n(options.withConfirm));\n }\n this.header.append(this.btnConfirm);\n ripple(this.btnConfirm);\n }\n\n this.container.append(this.header);\n if(options.body) {\n this.body = document.createElement('div');\n this.body.classList.add('popup-body');\n this.container.append(this.body);\n }\n\n if(buttons && buttons.length) {\n const buttonsDiv = document.createElement('div');\n buttonsDiv.classList.add('popup-buttons');\n\n if(buttons.length === 2) {\n buttonsDiv.classList.add('popup-buttons-row');\n }\n \n const buttonsElements = buttons.map(b => {\n const button = document.createElement('button');\n button.className = 'btn' + (b.isDanger ? ' danger' : ' primary');\n\n ripple(button);\n \n if(b.text) {\n button.innerHTML = b.text;\n } else {\n button.append(i18n(b.langKey, b.langArgs));\n }\n \n if(b.callback) {\n button.addEventListener('click', () => {\n b.callback();\n this.destroy();\n }, {once: true});\n } else if(b.isCancel) {\n button.addEventListener('click', () => {\n this.destroy();\n }, {once: true});\n }\n \n return button;\n });\n \n buttonsDiv.append(...buttonsElements);\n this.container.append(buttonsDiv);\n }\n\n this.element.append(this.container);\n }\n\n public show() {\n this.navigationItem = {\n type: 'popup',\n onPop: this.destroy,\n onEscape: this.onEscape\n };\n\n appNavigationController.pushItem(this.navigationItem);\n\n blurActiveElement(); // * hide mobile keyboard\n document.body.append(this.element);\n void this.element.offsetWidth; // reflow\n this.element.classList.add('active');\n rootScope.overlayIsActive = true;\n animationIntersector.checkAnimations(true);\n }\n\n public hide = () => {\n appNavigationController.back('popup');\n };\n\n private destroy = () => {\n this.onClose && this.onClose();\n this.element.classList.add('hiding');\n this.element.classList.remove('active');\n\n if(this.btnClose) this.btnClose.removeEventListener('click', this.hide);\n rootScope.overlayIsActive = false;\n\n appNavigationController.removeItem(this.navigationItem);\n this.navigationItem = undefined;\n\n setTimeout(() => {\n this.element.remove();\n this.onCloseAfterTimeout && this.onCloseAfterTimeout();\n animationIntersector.checkAnimations(false);\n }, 150);\n };\n}\n\nexport const addCancelButton = (buttons: PopupButton[]) => {\n const button = buttons.find(b => b.isCancel);\n if(!button) {\n buttons.push({\n langKey: 'Cancel',\n isCancel: true\n });\n }\n\n return buttons;\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport default function findUpTag(el: any, tag: string): HTMLElement {\n return el.closest(tag);\n /* if(el.tagName === tag) return el; // 03.02.2020\n\n while(el.parentElement) {\n el = el.parentElement;\n if(el.tagName === tag) \n return el;\n }\n return null; */\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport type { AccountPassword, AccountPasswordInputSettings, AccountUpdatePasswordSettings, InputCheckPasswordSRP, PasswordKdfAlgo } from '../../layer';\nimport type CryptoWorkerMethods from '../crypto/crypto_methods';\nimport { MOUNT_CLASS_TO } from '../../config/debug';\nimport appUsersManager from '../appManagers/appUsersManager';\nimport apiManager from './mtprotoworker';\n//import { computeCheck } from \"../crypto/srp\";\n\nexport class PasswordManager {\n public getState(): Promise<AccountPassword> {\n return apiManager.invokeApi('account.getPassword').then((result) => {\n return result;\n });\n }\n\n public updateSettings(settings: {\n hint?: string,\n email?: string,\n newPassword?: string,\n currentPassword?: string\n } = {}) {\n //state = Object.assign({}, state);\n //state.new_algo = Object.assign({}, state.new_algo);\n\n return this.getState().then(state => {\n let currentHashPromise: ReturnType<CryptoWorkerMethods['computeSRP']>;\n let newHashPromise: Promise<Uint8Array>;\n const params: AccountUpdatePasswordSettings = {\n password: null,\n new_settings: {\n _: 'account.passwordInputSettings',\n hint: settings.hint,\n email: settings.email\n }\n };\n \n if(settings.currentPassword) {\n currentHashPromise = apiManager.computeSRP(settings.currentPassword, state);\n } else {\n currentHashPromise = Promise.resolve({\n _: 'inputCheckPasswordEmpty'\n });\n }\n \n // * https://core.telegram.org/api/srp#setting-a-new-2fa-password, but still there is a mistake, TDesktop passes 'new_algo' everytime\n const newAlgo = state.new_algo as PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow;\n const salt1 = new Uint8Array(newAlgo.salt1.length + 32);\n salt1.randomize();\n salt1.set(newAlgo.salt1, 0);\n newAlgo.salt1 = salt1;\n \n if(settings.newPassword) {\n newHashPromise = apiManager.computeSRP(settings.newPassword, state, true) as any;\n } else {\n newHashPromise = Promise.resolve(new Uint8Array());\n }\n \n return Promise.all([currentHashPromise, newHashPromise]).then((hashes) => {\n params.password = hashes[0];\n params.new_settings.new_algo = newAlgo;\n params.new_settings.new_password_hash = hashes[1];\n \n return apiManager.invokeApi('account.updatePasswordSettings', params);\n });\n });\n }\n\n public check(password: string, state: AccountPassword, options: any = {}) {\n return apiManager.computeSRP(password, state).then((inputCheckPassword) => {\n //console.log('SRP', inputCheckPassword);\n return apiManager.invokeApi('auth.checkPassword', {\n password: inputCheckPassword\n }, options).then(auth => {\n if(auth._ === 'auth.authorization') {\n appUsersManager.saveApiUser(auth.user);\n apiManager.setUserAuth(auth.user.id);\n }\n\n return auth;\n });\n });\n }\n\n public confirmPasswordEmail(code: string) {\n return apiManager.invokeApi('account.confirmPasswordEmail', {code});\n }\n\n public resendPasswordEmail() {\n return apiManager.invokeApi('account.resendPasswordEmail');\n }\n\n public cancelPasswordEmail() {\n return apiManager.invokeApi('account.cancelPasswordEmail');\n }\n\n /* public requestRecovery(options: any = {}) {\n return apiManager.invokeApi('auth.requestPasswordRecovery', {}, options);\n }\n\n public recover(code: any, options: any = {}) {\n return apiManager.invokeApi('auth.recoverPassword', {\n code\n }, options);\n } */\n}\n\nconst passwordManager = new PasswordManager();\nMOUNT_CLASS_TO.passwordManager = passwordManager;\nexport default passwordManager;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { cancelEvent } from \"../helpers/dom\";\nimport InputField, { InputFieldOptions } from \"./inputField\";\n\nexport default class PasswordInputField extends InputField {\n public passwordVisible = false;\n public toggleVisible: HTMLElement;\n public onVisibilityClickAdditional: () => void;\n\n constructor(options: InputFieldOptions = {}) {\n super({\n plainText: true,\n ...options\n });\n\n const input = this.input as HTMLInputElement;\n input.type = 'password';\n input.setAttribute('required', '');\n input.autocomplete = 'off';\n /* input.readOnly = true;\n\n input.addEventListener('focus', () => {\n input.removeAttribute('readonly');\n }, {once: true}); */\n\n // * https://stackoverflow.com/a/35949954/6758968\n const stealthy = document.createElement('input');\n stealthy.classList.add('stealthy');\n stealthy.tabIndex = -1;\n stealthy.type = 'password';\n input.parentElement.prepend(stealthy);\n input.parentElement.insertBefore(stealthy.cloneNode(), input.nextSibling);\n\n const toggleVisible = this.toggleVisible = document.createElement('span');\n toggleVisible.classList.add('toggle-visible', 'tgico');\n\n this.container.classList.add('input-field-password');\n this.container.append(toggleVisible);\n\n toggleVisible.addEventListener('click', this.onVisibilityClick);\n toggleVisible.addEventListener('touchend', this.onVisibilityClick);\n }\n\n public onVisibilityClick = (e: Event) => {\n cancelEvent(e);\n this.passwordVisible = !this.passwordVisible;\n\n this.toggleVisible.classList.toggle('eye-hidden', this.passwordVisible);\n (this.input as HTMLInputElement).type = this.passwordVisible ? 'text' : 'password';\n this.onVisibilityClickAdditional && this.onVisibilityClickAdditional();\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport lottieLoader, { RLottiePlayer } from \"../../lib/lottieLoader\";\nimport PasswordInputField from \"../passwordInputField\";\n\nexport default class PasswordMonkey {\n public container: HTMLElement;\n public animation: RLottiePlayer;\n public needFrame = 0;\n protected loadPromise: Promise<void>;\n\n constructor(protected passwordInputField: PasswordInputField, protected size: number) {\n this.container = document.createElement('div');\n this.container.classList.add('media-sticker-wrapper');\n }\n\n public load() {\n if(this.loadPromise) return this.loadPromise;\n return this.loadPromise = lottieLoader.loadAnimationFromURL({\n container: this.container,\n loop: false,\n autoplay: false,\n width: this.size,\n height: this.size,\n noCache: true\n //}, 'assets/img/TwoFactorSetupMonkeyClose.tgs').then(_animation => {\n }, 'assets/img/TwoFactorSetupMonkeyPeek.tgs').then(_animation => {\n //return;\n this.animation = _animation;\n this.animation.addEventListener('enterFrame', currentFrame => {\n //console.log('enterFrame', currentFrame, this.needFrame);\n\n if((this.animation.direction === 1 && currentFrame >= this.needFrame) ||\n (this.animation.direction === -1 && currentFrame <= this.needFrame)) {\n this.animation.setSpeed(1);\n this.animation.pause();\n } \n });\n\n this.passwordInputField.onVisibilityClickAdditional = () => {\n if(this.passwordInputField.passwordVisible) {\n this.animation.setDirection(1);\n this.animation.curFrame = 0;\n this.needFrame = 16;\n this.animation.play();\n } else {\n this.animation.setDirection(-1);\n this.animation.curFrame = 16;\n this.needFrame = 0;\n this.animation.play();\n }\n };\n\n return lottieLoader.waitForFirstFrame(_animation);\n });\n }\n\n public remove() {\n if(this.animation) {\n this.animation.remove();\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nfunction resizeableImage(originalImage: HTMLImageElement, canvas?: HTMLCanvasElement) {\n let cropComponent: HTMLDivElement, \n container: HTMLDivElement, \n cropImage: HTMLImageElement, \n event_state: Partial<{ \n mouse_x: number, \n mouse_y: number, \n container_width: number, \n container_height: number, \n container_left: number, \n container_top: number\n }> = {}, \n keyZoomValue = 4.0, \n MINWIDTH = 50, \n MINHEIGHT = 50, \n CROPWIDTH = 200, \n CROPHEIGHT = 200, \n cropLeft = 0, \n cropTop = 0, \n cropWidth = 0, \n cropHeight = 0,\n scaledRatio = 0;\n \n if(originalImage.complete) init();\n else originalImage.onload = init;\n \n function removeHandlers() {\n container.removeEventListener('mousedown', startMoving);\n container.removeEventListener('touchstart', startMoving);\n container.removeEventListener('wheel', resizing);\n \n document.removeEventListener('mouseup', endMoving);\n document.removeEventListener('touchend', endMoving);\n document.removeEventListener('mousemove', moving);\n document.removeEventListener('touchmove', moving);\n document.removeEventListener('keypress', keyHandler);\n\n cropComponent.remove();\n container.remove();\n cropImage.remove();\n }\n \n function addHandlers() {\n container.addEventListener('mousedown', startMoving, false);\n container.addEventListener('touchstart', startMoving, false);\n container.addEventListener('wheel', resizing, false);\n \n document.addEventListener('keypress', keyHandler, false);\n //document.querySelector('.btn-crop').addEventListener('click', openCropCanvasImg);\n }\n \n function init() {\n originalImage.classList.add('crop-blur');\n originalImage.draggable = false;\n \n cropImage = new Image();\n cropImage.src = originalImage.src;\n cropImage.draggable = false;\n cropImage.classList.add('crop-overlay-image');\n \n if(!canvas) {\n canvas = document.createElement('canvas');\n }\n \n cropComponent = document.createElement('div');\n cropComponent.classList.add('crop-component');\n \n container = document.createElement('div');\n container.classList.add('crop-overlay');\n \n const overlayColor = document.createElement('div');\n overlayColor.classList.add('crop-overlay-color');\n \n cropComponent.appendChild(container);\n const wrapper = originalImage.parentNode as HTMLElement;\n wrapper.appendChild(cropComponent);\n cropComponent.appendChild(cropImage);\n cropComponent.appendChild(originalImage);\n cropComponent.appendChild(overlayColor);\n container.appendChild(cropImage);\n\n cropImage.style.maxWidth = originalImage.width + 'px';\n\n scaledRatio = originalImage.naturalWidth / originalImage.offsetWidth;\n \n const left = originalImage.offsetWidth / 2 - CROPWIDTH / 2;\n const top = originalImage.offsetHeight / 2 - CROPHEIGHT / 2;\n \n updateCropSize(CROPWIDTH, CROPHEIGHT);\n updateCropImage(left, top);\n updateContainer(left, top);\n addHandlers();\n //crop();\n }\n \n function updateCropSize(width: number, height: number) {\n cropWidth = width * scaledRatio;\n cropHeight = height * scaledRatio;\n\n container.style.width = width + 'px';\n container.style.height = height + 'px';\n }\n \n function updateCropImage(left: number, top: number) {\n cropTop = top * scaledRatio;\n cropLeft = left * scaledRatio;\n\n cropImage.style.top = -top + 'px';\n cropImage.style.left = -left + 'px';\n }\n \n function updateContainer(left: number, top: number) {\n container.style.top = top + 'px';\n container.style.left = left + 'px';\n }\n \n // Save the initial event details and container state\n function saveEventState(e: any) {\n event_state.container_width = container.offsetWidth;\n event_state.container_height = container.offsetHeight;\n \n event_state.container_left = container.offsetLeft;\n event_state.container_top = container.offsetTop;\n \n event_state.mouse_x = (e.clientX || e.pageX || e.touches && e.touches[0].clientX) + window.scrollX;\n event_state.mouse_y = (e.clientY || e.pageY || e.touches && e.touches[0].clientY) + window.scrollY;\n }\n \n function imgZoom(zoom: number) {\n zoom = zoom * Math.PI * 2\n let newWidth = Math.floor(container.clientWidth + zoom), \n newHeight = Math.floor(container.clientHeight + zoom), \n w = cropImage.clientWidth, \n h = cropImage.clientHeight, \n left: number, \n top: number, \n right: number, \n bottom: number;\n \n if(newWidth < MINWIDTH) {\n return;\n } else if(newWidth > w) {\n return;\n }\n \n left = container.offsetLeft - (zoom / 2);\n top = container.offsetTop - (zoom / 2);\n right = left + newWidth;\n bottom = top + newHeight;\n \n if(left < 0) left = 0;\n if(top < 0) top = 0;\n\n if(right > w) return;\n if(bottom > h) return;\n\n updateCropSize(newWidth, newWidth);\n updateCropImage(left, top);\n updateContainer(left, top);\n //crop();\n }\n \n function keyHandler(e: KeyboardEvent) {\n e.preventDefault();\n \n switch (String.fromCharCode(e.charCode)) {\n case '+' :\n imgZoom(keyZoomValue);\n break;\n case '-' :\n imgZoom(-keyZoomValue);\n break;\n }\n }\n \n function resizing(e: any) {\n e.preventDefault();\n imgZoom(e.deltaY > 0 ? 1 : -1);\n }\n \n function startMoving(e: MouseEvent | TouchEvent) {\n e.preventDefault();\n e.stopPropagation();\n \n saveEventState(e);\n \n document.addEventListener('mousemove', moving);\n document.addEventListener('touchmove', moving);\n document.addEventListener('mouseup', endMoving);\n document.addEventListener('touchend', endMoving);\n }\n \n function endMoving(e: MouseEvent | TouchEvent) {\n e.preventDefault();\n \n document.removeEventListener('mouseup', endMoving);\n document.removeEventListener('touchend', endMoving);\n document.removeEventListener('mousemove', moving);\n document.removeEventListener('touchmove', moving);\n }\n \n function moving(e: any) {\n let currentTouch = {x: 0, y: 0}, \n left: number, \n top: number, \n w: number, \n h: number;\n \n e.preventDefault();\n e.stopPropagation();\n \n currentTouch.x = e.pageX || e.touches && e.touches[0].pageX;\n currentTouch.y = e.pageY || e.touches && e.touches[0].pageY;\n \n left = currentTouch.x - (event_state.mouse_x - event_state.container_left);\n top = currentTouch.y - (event_state.mouse_y - event_state.container_top);\n w = container.offsetWidth;\n h = container.offsetHeight;\n \n if(left < 0) left = 0;\n else if(left > cropImage.offsetWidth - w) left = cropImage.offsetWidth - w;\n\n if(top < 0) top = 0;\n else if(top > cropImage.offsetHeight - h) top = cropImage.offsetHeight - h;\n \n updateCropImage(left, top);\n updateContainer(left, top);\n //crop();\n }\n\n function crop() {\n canvas.width = cropWidth;\n canvas.height = cropHeight;\n \n const ctx = canvas.getContext('2d');\n ctx.drawImage(originalImage,\n cropLeft, cropTop,\n cropWidth, cropHeight,\n 0, 0,\n cropWidth, cropHeight\n );\n }\n \n return {crop, removeHandlers};\n}\n\nexport default resizeableImage;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDownloadManager from \"../../lib/appManagers/appDownloadManager\";\nimport resizeableImage from \"../../lib/cropper\";\nimport PopupElement from \".\";\nimport { ripple } from \"../ripple\";\nimport { _i18n } from \"../../lib/langPack\";\n\nexport default class PopupAvatar extends PopupElement {\n private cropContainer: HTMLElement;\n private input: HTMLInputElement;\n private btnSubmit: HTMLElement;\n private h6: HTMLElement;\n\n private image = new Image();\n\n private canvas: HTMLCanvasElement;\n private blob: Blob;\n private cropper = {\n crop: () => {},\n removeHandlers: () => {}\n };\n\n private onCrop: (upload: () => ReturnType<typeof appDownloadManager.upload>) => void;\n\n constructor() {\n super('popup-avatar', null, {closable: true});\n\n this.h6 = document.createElement('h6');\n _i18n(this.h6, 'Popup.Avatar.Title');\n\n this.btnClose.classList.remove('btn-icon');\n\n this.header.append(this.h6);\n\n this.cropContainer = document.createElement('div');\n this.cropContainer.classList.add('crop');\n this.cropContainer.append(this.image);\n\n this.input = document.createElement('input');\n this.input.type = 'file';\n this.input.style.display = 'none';\n this.input.addEventListener('change', (e: any) => {\n const file = e.target.files[0];\n if(!file) {\n return;\n }\n \n const reader = new FileReader();\n reader.onload = (e) => {\n const contents = e.target.result as string;\n \n this.image = new Image();\n this.cropContainer.append(this.image);\n this.image.src = contents;\n \n this.image.onload = () => {\n /* let {w, h} = calcImageInBox(this.image.naturalWidth, this.image.naturalHeight, 460, 554);\n cropContainer.style.width = w + 'px';\n cropContainer.style.height = h + 'px'; */\n this.show();\n \n this.cropper = resizeableImage(this.image, this.canvas);\n this.input.value = '';\n };\n };\n \n reader.readAsDataURL(file);\n }, false);\n\n this.btnSubmit = document.createElement('button');\n this.btnSubmit.className = 'btn-primary btn-color-primary btn-circle btn-crop btn-icon tgico-check z-depth-1';\n ripple(this.btnSubmit);\n this.btnSubmit.addEventListener('click', () => {\n this.cropper.crop();\n this.btnClose.click();\n\n this.canvas.toBlob(blob => {\n this.blob = blob; // save blob to send after reg\n this.darkenCanvas();\n this.resolve();\n }, 'image/jpeg', 1);\n });\n\n this.container.append(this.cropContainer, this.btnSubmit, this.input);\n\n this.onCloseAfterTimeout = () => {\n this.cropper.removeHandlers();\n if(this.image) {\n this.image.remove();\n }\n };\n }\n\n private resolve() {\n this.onCrop(() => {\n return appDownloadManager.upload(this.blob);\n });\n }\n\n public open(postCanvas: HTMLCanvasElement, onCrop: PopupAvatar['onCrop']) {\n this.canvas = postCanvas;\n this.onCrop = onCrop;\n\n this.input.click();\n }\n\n public darkenCanvas() {\n let ctx = this.canvas.getContext('2d');\n ctx.fillStyle = \"rgba(0, 0, 0, 0.3)\";\n ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDialogsManager from \"../lib/appManagers/appDialogsManager\";\nimport Scrollable from \"./scrollable\";\nimport appMessagesManager from \"../lib/appManagers/appMessagesManager\";\nimport InputSearch from \"./inputSearch\";\n\nexport class SearchGroup {\n container: HTMLDivElement;\n nameEl: HTMLDivElement;\n list: HTMLUListElement;\n\n constructor(public name: string, public type: string, private clearable = true, className?: string, clickable = true, public autonomous = true, public onFound?: () => void) {\n this.list = appDialogsManager.createChatList();\n this.container = document.createElement('div');\n if(className) this.container.className = className;\n \n if(name) {\n this.nameEl = document.createElement('div');\n this.nameEl.classList.add('search-group__name');\n this.nameEl.innerText = name;\n this.container.append(this.nameEl);\n }\n \n this.container.classList.add('search-group', 'search-group-' + type);\n this.container.append(this.list);\n this.container.style.display = 'none';\n\n if(clickable) {\n appDialogsManager.setListClickListener(this.list, onFound, undefined, autonomous);\n }\n }\n\n clear() {\n this.container.style.display = 'none';\n\n if(this.clearable) {\n this.list.innerHTML = '';\n }\n }\n\n setActive() {\n this.container.style.display = '';\n }\n\n toggle() {\n if(this.list.childElementCount) {\n this.setActive();\n } else {\n this.clear();\n }\n }\n}\n\nexport type SearchGroupType = 'contacts' | 'globalContacts' | 'messages' | string;\n\nexport default class AppSearch {\n private minMsgId = 0;\n private loadedCount = -1;\n private foundCount = -1;\n\n private searchPromise: Promise<void> = null;\n private searchTimeout: number = 0;\n\n private query = '';\n\n public listsContainer: HTMLDivElement = null;\n\n private peerId = 0; // 0 - means global\n private threadId = 0;\n\n private scrollable: Scrollable;\n\n constructor(public container: HTMLElement, public searchInput: InputSearch, public searchGroups: {[group in SearchGroupType]: SearchGroup}, public onSearch?: (count: number) => void) {\n this.scrollable = new Scrollable(this.container);\n this.listsContainer = this.scrollable.container as HTMLDivElement;\n for(let i in this.searchGroups) {\n this.listsContainer.append(this.searchGroups[i as SearchGroupType].container);\n }\n\n if(this.searchGroups.messages) {\n this.scrollable.setVirtualContainer(this.searchGroups.messages.list);\n }\n\n this.searchInput.onChange = (value) => {\n /* if(!value.trim()) {\n //this.peerId = 0;\n return;\n } */\n \n this.query = value;\n this.reset(false);\n this.searchMore();\n };\n\n this.scrollable.onScrolledBottom = () => {\n if(!this.query.trim()) return;\n \n if(!this.searchTimeout) {\n this.searchTimeout = window.setTimeout(() => {\n this.searchMore();\n this.searchTimeout = 0;\n }, 0);\n }\n };\n }\n\n public reset(all = true) {\n if(all) {\n this.searchInput.value = '';\n this.query = '';\n this.peerId = 0;\n this.threadId = 0;\n }\n\n this.minMsgId = 0;\n this.loadedCount = -1;\n this.foundCount = -1;\n\n for(let i in this.searchGroups) {\n this.searchGroups[i as SearchGroupType].clear();\n }\n \n this.searchPromise = null;\n }\n\n public beginSearch(peerId?: number, threadId?: number) {\n if(peerId) {\n this.peerId = peerId;\n }\n\n if(threadId) {\n this.threadId = threadId;\n }\n \n this.searchInput.input.focus();\n }\n\n public searchMore() {\n if(this.searchPromise) return this.searchPromise;\n \n const query = this.query;\n \n if(!query.trim()) {\n this.onSearch && this.onSearch(0);\n return;\n }\n \n if(this.foundCount !== -1 && this.loadedCount >= this.foundCount) {\n return Promise.resolve();\n }\n \n const maxId = this.minMsgId || 0;\n\n return this.searchPromise = appMessagesManager.getSearch({\n peerId: this.peerId, \n query, \n inputFilter: {_: 'inputMessagesFilterEmpty'}, \n maxId, \n limit: 20,\n threadId: this.threadId\n }).then(res => {\n this.searchPromise = null;\n \n if(this.searchInput.value !== query) {\n return;\n }\n \n //console.log('input search result:', this.peerId, query, null, maxId, 20, res);\n \n const {count, history} = res;\n \n if(history.length && history[0].mid === this.minMsgId) {\n history.shift();\n }\n \n const searchGroup = this.searchGroups.messages;\n\n history.forEach((message) => {\n const {dialog, dom} = appDialogsManager.addDialogNew({\n dialog: message.peerId, \n container: this.scrollable/* searchGroup.list */, \n drawStatus: false,\n avatarSize: 54\n });\n appDialogsManager.setLastMessage(dialog, message, dom, query);\n });\n\n searchGroup.toggle();\n \n this.minMsgId = history.length && history[history.length - 1].mid;\n \n if(this.loadedCount === -1) {\n this.loadedCount = 0;\n }\n this.loadedCount += history.length;\n \n if(this.foundCount === -1) {\n this.foundCount = count;\n this.onSearch && this.onSearch(this.foundCount);\n }\n }).catch(err => {\n console.error('search error', err);\n this.searchPromise = null;\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\n//import { getRichValue } from \"../helpers/dom\";\nimport { LangPackKey } from \"../lib/langPack\";\nimport InputField from \"./inputField\";\n\nexport default class InputSearch {\n public container: HTMLElement;\n public input: HTMLElement;\n public inputField: InputField;\n public clearBtn: HTMLElement;\n\n public prevValue = '';\n public timeout = 0;\n public onChange: (value: string) => void;\n public onClear: () => void;\n\n constructor(placeholder: LangPackKey, onChange?: (value: string) => void) {\n this.inputField = new InputField({\n placeholder,\n plainText: true\n });\n\n this.container = this.inputField.container;\n this.container.classList.remove('input-field');\n this.container.classList.add('input-search');\n\n this.onChange = onChange;\n\n this.input = this.inputField.input;\n this.input.classList.add('input-search-input');\n\n const searchIcon = document.createElement('i');\n searchIcon.classList.add('tgico', 'tgico-search');\n\n this.clearBtn = document.createElement('i');\n this.clearBtn.classList.add('tgico', 'btn-icon', 'tgico-close');\n\n this.input.addEventListener('input', this.onInput);\n this.clearBtn.addEventListener('click', this.onClearClick);\n\n this.container.append(searchIcon, this.clearBtn);\n }\n \n onInput = () => {\n if(!this.onChange) return;\n\n let value = this.value;\n\n //this.input.classList.toggle('is-empty', !value.trim());\n\n if(value !== this.prevValue) {\n this.prevValue = value;\n clearTimeout(this.timeout);\n this.timeout = window.setTimeout(() => {\n this.onChange(value);\n }, 200);\n }\n };\n\n onClearClick = () => {\n this.value = '';\n this.onChange && this.onChange('');\n this.onClear && this.onClear();\n };\n\n get value() {\n return this.inputField.value;\n }\n\n set value(value: string) {\n this.prevValue = value;\n clearTimeout(this.timeout);\n this.inputField.value = value;\n }\n\n public remove() {\n clearTimeout(this.timeout);\n this.input.removeEventListener('input', this.onInput);\n this.clearBtn.removeEventListener('click', this.onClearClick);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { RootScope } from \"../lib/rootScope\";\nimport { ArgumentTypes } from \"../types\";\n\n/* export type Listener<T extends ListenerElement> = {\n element: ListenerElement, \n event: ListenerEvent<T>, \n callback: ListenerCallback<T>, \n options?: ListenerOptions\n};\n\nexport type ListenerElement = HTMLElement | RootScope;\nexport type ListenerEvent<T extends ListenerElement> = ArgumentTypes<T['addEventListener']>[0];\nexport type ListenerCallback<T extends ListenerElement> = ArgumentTypes<T['addEventListener']>[1];\nexport type ListenerOptions = any; */\nexport type Listener<T extends ListenerElement> = {\n element: ListenerElement, \n event: ListenerEvent<T>, \n callback: ListenerCallback, \n options?: ListenerOptions\n};\n\nexport type ListenerElement = Window | Document | HTMLElement | Element | RootScope | any;\n//export type ListenerEvent<T extends ListenerElement> = ArgumentTypes<T['addEventListener']>[0];\nexport type ListenerEvent<T extends ListenerElement> = string;\nexport type ListenerCallback = (...args: any[]) => any;\nexport type ListenerOptions = any;\n\nexport default class ListenerSetter {\n private listeners: Set<Listener<any>> = new Set();\n\n public add<T extends ListenerElement>(element: T, event: ListenerEvent<T>, callback: ListenerCallback, options?: ListenerOptions) {\n const listener: Listener<T> = {element, event, callback, options};\n this.addManual(listener);\n return listener;\n }\n\n public addManual<T extends ListenerElement>(listener: Listener<T>) {\n // @ts-ignore\n listener.element.addEventListener(listener.event, listener.callback, listener.options);\n this.listeners.add(listener);\n }\n\n public remove<T extends ListenerElement>(listener: Listener<T>) {\n // @ts-ignore\n listener.element.removeEventListener(listener.event, listener.callback, listener.options);\n this.listeners.delete(listener);\n }\n\n public removeManual<T extends ListenerElement>(element: T, event: ListenerEvent<T>, callback: ListenerCallback, options?: ListenerOptions) {\n let listener: Listener<T>;\n for(const _listener of this.listeners) {\n if(_listener.element === element && _listener.event === event && _listener.callback === callback && _listener.options === options) {\n listener = _listener;\n break;\n }\n }\n\n if(listener) {\n this.remove(listener);\n }\n }\n\n public removeAll() {\n this.listeners.forEach(listener => {\n this.remove(listener);\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport Button from \"./button\";\n\nconst ButtonIcon = (className: string, options: Partial<{noRipple: true, onlyMobile: true, asDiv: boolean}> = {}) => {\n const button = Button('btn-icon', {icon: className, ...options});\n return button;\n};\n\nexport default ButtonIcon;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport EventListenerBase from \"../helpers/eventListenerBase\";\nimport ListenerSetter from \"../helpers/listenerSetter\";\nimport { i18n, LangPackKey } from \"../lib/langPack\";\nimport ButtonIcon from \"./buttonIcon\";\nimport Scrollable from \"./scrollable\";\nimport SidebarSlider from \"./slider\";\n\nexport interface SliderTab {\n onOpen?: () => void,\n onOpenAfterTimeout?: () => void,\n onClose?: () => void,\n onCloseAfterTimeout?: () => void\n}\n\nexport interface SliderSuperTabConstructable {\n new(slider: SidebarSlider, destroyable: boolean): SliderSuperTab;\n}\n\nexport default class SliderSuperTab implements SliderTab {\n public container: HTMLElement;\n\n public header: HTMLElement;\n public closeBtn: HTMLElement;\n public title: HTMLElement;\n\n public content: HTMLElement;\n public scrollable: Scrollable;\n\n public slider: SidebarSlider;\n public destroyable: boolean;\n public listenerSetter: ListenerSetter;\n\n constructor(slider: SidebarSlider, destroyable?: boolean) {\n this._constructor(slider, destroyable);\n }\n\n public _constructor(slider: SidebarSlider, destroyable = true): any {\n this.slider = slider;\n this.destroyable = destroyable;\n\n this.container = document.createElement('div');\n this.container.classList.add('sidebar-slider-item');\n\n // * Header\n this.header = document.createElement('div');\n this.header.classList.add('sidebar-header');\n\n this.closeBtn = ButtonIcon('left sidebar-close-button', {noRipple: true});\n this.title = document.createElement('div');\n this.title.classList.add('sidebar-header__title');\n this.header.append(this.closeBtn, this.title);\n\n // * Content\n this.content = document.createElement('div');\n this.content.classList.add('sidebar-content');\n\n this.scrollable = new Scrollable(this.content, undefined, undefined, true);\n\n this.container.append(this.header, this.content);\n\n this.slider.addTab(this);\n \n this.listenerSetter = new ListenerSetter();\n }\n\n public close() {\n return this.slider.closeTab(this);\n }\n\n public async open(...args: any[]) {\n if(this.init) {\n try {\n const result = this.init();\n this.init = null;\n\n if(result instanceof Promise) {\n await result;\n }\n } catch(err) {\n console.error('open tab error', err);\n }\n }\n\n return this.slider.selectTab(this);\n }\n\n protected init(): Promise<any> | any {\n\n }\n\n public onCloseAfterTimeout() {\n if(this.destroyable) { // ! WARNING, пока что это будет работать только с самой последней внутренней вкладкой !\n this.slider.tabs.delete(this);\n this.container.remove();\n }\n\n if(this.listenerSetter) {\n this.listenerSetter.removeAll();\n }\n }\n\n protected setTitle(key: LangPackKey) {\n this.title.innerHTML = '';\n this.title.append(i18n(key));\n }\n}\n\nexport class SliderSuperTabEventable extends SliderSuperTab {\n public eventListener: EventListenerBase<{\n destroy: () => void\n }>;\n\n constructor(slider: SidebarSlider) {\n super(slider);\n this.eventListener = new EventListenerBase();\n }\n\n onCloseAfterTimeout() {\n this.eventListener.dispatchEvent('destroy');\n this.eventListener.cleanup();\n return super.onCloseAfterTimeout();\n }\n}\n\n/* // @ts-ignore\ninterface SliderSuperEventsTab extends SliderSuperTab, EventListenerBase<{}> {\n superConstructor: (...args: any[]) => any;\n}\nclass SliderSuperEventsTab implements SliderSuperEventsTab {\n constructor(slider: SidebarSlider) {\n this.superConstructor([slider, true]);\n }\n}\napplyMixins(SliderSuperEventsTab, [SliderSuperTab, EventListenerBase]);\n\n(window as any).lol = SliderSuperEventsTab\n\nexport {SliderSuperEventsTab}; */\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { attachClickEvent } from \"../helpers/dom\";\nimport { horizontalMenu } from \"./horizontalMenu\";\nimport { TransitionSlider } from \"./transition\";\nimport appNavigationController, { NavigationItem } from \"./appNavigationController\";\nimport SliderSuperTab, { SliderSuperTabConstructable, SliderTab } from \"./sliderTab\";\nimport { safeAssign } from \"../helpers/object\";\n\nconst TRANSITION_TIME = 250;\n\nexport type {SliderTab};\nexport {SliderSuperTab};\n\nexport default class SidebarSlider {\n protected _selectTab: ReturnType<typeof horizontalMenu>;\n public historyTabIds: (number | SliderSuperTab)[] = []; // * key is any, since right sidebar is ugly nowz\n public tabsContainer: HTMLElement;\n public sidebarEl: HTMLElement;\n public tabs: Map<any, SliderTab>; // * key is any, since right sidebar is ugly now\n private canHideFirst = false;\n private navigationType: NavigationItem['type']\n\n constructor(options: {\n sidebarEl: SidebarSlider['sidebarEl'],\n tabs?: SidebarSlider['tabs'],\n canHideFirst?: SidebarSlider['canHideFirst'],\n navigationType: SidebarSlider['navigationType']\n }) {\n safeAssign(this, options);\n\n if(!this.tabs) {\n this.tabs = new Map();\n }\n\n this.tabsContainer = this.sidebarEl.querySelector('.sidebar-slider');\n this._selectTab = TransitionSlider(this.tabsContainer, 'navigation', TRANSITION_TIME);\n if(!this.canHideFirst) {\n this._selectTab(0);\n }\n\n Array.from(this.sidebarEl.querySelectorAll('.sidebar-close-button') as any as HTMLElement[]).forEach(el => {\n attachClickEvent(el, this.onCloseBtnClick);\n });\n }\n\n public onCloseBtnClick = () => {\n const item = appNavigationController.findItemByType(this.navigationType);\n if(item) {\n appNavigationController.back(this.navigationType);\n } else if(this.historyTabIds.length) {\n this.closeTab(this.historyTabIds[this.historyTabIds.length - 1]);\n }\n // this.closeTab();\n };\n\n public closeTab = (id?: number | SliderSuperTab, animate?: boolean, isNavigation?: boolean) => {\n if(id !== undefined && this.historyTabIds[this.historyTabIds.length - 1] !== id) {\n return false;\n }\n\n //console.log('sidebar-close-button click:', this.historyTabIDs);\n const closingId = this.historyTabIds.pop(); // pop current\n this.onCloseTab(closingId, animate, isNavigation);\n\n const tab = this.historyTabIds[this.historyTabIds.length - 1];\n this._selectTab(tab !== undefined ? (tab instanceof SliderSuperTab ? tab.container : tab) : (this.canHideFirst ? -1 : 0), animate);\n return true;\n };\n\n public selectTab(id: number | SliderSuperTab): boolean {\n /* if(id instanceof SliderSuperTab) {\n id = id.id;\n } */\n\n if(this.historyTabIds[this.historyTabIds.length - 1] === id) {\n return false;\n }\n\n const tab: SliderTab = id instanceof SliderSuperTab ? id : this.tabs.get(id);\n if(tab) {\n if(tab.onOpen) {\n tab.onOpen();\n }\n \n if(tab.onOpenAfterTimeout) {\n setTimeout(() => {\n tab.onOpenAfterTimeout();\n }, TRANSITION_TIME);\n }\n }\n\n //if(!this.canHideFirst || this.historyTabIds.length) {\n appNavigationController.pushItem({\n type: this.navigationType, \n onPop: (canAnimate) => {\n this.closeTab(undefined, canAnimate, true);\n return true;\n }\n });\n //}\n \n this.historyTabIds.push(id);\n this._selectTab(id instanceof SliderSuperTab ? id.container : id);\n return true;\n }\n\n public removeTabFromHistory(id: number | SliderSuperTab) {\n this.historyTabIds.findAndSplice(i => i === id);\n this.onCloseTab(id, undefined);\n }\n\n public sliceTabsUntilTab(tabConstructor: SliderSuperTabConstructable, preserveTab: SliderSuperTab) {\n for(let i = this.historyTabIds.length - 1; i >= 0; --i) {\n const tab = this.historyTabIds[i];\n if(tab === preserveTab) continue;\n else if(tab instanceof tabConstructor) {\n break;\n }\n\n this.removeTabFromHistory(tab);\n //appNavigationController.removeByType(this.navigationType, true);\n }\n }\n\n public getTab(tabConstructor: SliderSuperTabConstructable) {\n return this.historyTabIds.find(t => t instanceof tabConstructor) as SliderSuperTab;\n }\n\n public isTabExists(tabConstructor: SliderSuperTabConstructable) {\n return !!this.getTab(tabConstructor);\n }\n\n protected onCloseTab(id: number | SliderSuperTab, animate: boolean, isNavigation?: boolean) {\n if(!isNavigation) {\n appNavigationController.removeByType(this.navigationType, true);\n }\n\n const tab: SliderTab = id instanceof SliderSuperTab ? id : this.tabs.get(id);\n if(tab) {\n if(tab.onClose) {\n tab.onClose();\n }\n\n if(tab.onCloseAfterTimeout) {\n setTimeout(() => {\n tab.onCloseAfterTimeout();\n }, TRANSITION_TIME);\n }\n }\n }\n\n public addTab(tab: SliderSuperTab) {\n if(!tab.container.parentElement) {\n this.tabsContainer.append(tab.container);\n\n if(tab.closeBtn) {\n tab.closeBtn.addEventListener('click', this.onCloseBtnClick);\n }\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { CancellablePromise } from \"../helpers/cancellablePromise\";\nimport type { InputFile } from \"../layer\";\nimport PopupAvatar from \"./popups/avatar\";\n\nexport default class AvatarEdit {\n public container: HTMLElement;\n private canvas: HTMLCanvasElement;\n private icon: HTMLSpanElement;\n\n constructor(onChange: (uploadAvatar: () => CancellablePromise<InputFile>) => void) {\n this.container = document.createElement('div');\n this.container.classList.add('avatar-edit');\n\n this.canvas = document.createElement('canvas');\n this.canvas.classList.add('avatar-edit-canvas');\n\n this.icon = document.createElement('span');\n this.icon.classList.add('tgico', 'tgico-cameraadd');\n\n this.container.append(this.canvas, this.icon);\n\n this.container.addEventListener('click', () => {\n new PopupAvatar().open(this.canvas, onChange);\n });\n }\n\n public clear() {\n const ctx = this.canvas.getContext('2d');\n ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appSidebarLeft from \"..\";\nimport { InputFile } from \"../../../layer\";\nimport appChatsManager from \"../../../lib/appManagers/appChatsManager\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport { SearchGroup } from \"../../appSearch\";\nimport Button from \"../../button\";\nimport InputField from \"../../inputField\";\nimport { SliderSuperTab } from \"../../slider\";\nimport AvatarEdit from \"../../avatarEdit\";\nimport { i18n } from \"../../../lib/langPack\";\n\nexport default class AppNewGroupTab extends SliderSuperTab {\n private searchGroup = new SearchGroup(' ', 'contacts', true, 'new-group-members disable-hover', false);\n private avatarEdit: AvatarEdit;\n private uploadAvatar: () => Promise<InputFile> = null;\n private userIds: number[];\n private nextBtn: HTMLButtonElement;\n private groupNameInputField: InputField;\n\n protected init() {\n this.container.classList.add('new-group-container');\n this.setTitle('NewGroup');\n\n this.avatarEdit = new AvatarEdit((_upload) => {\n this.uploadAvatar = _upload;\n });\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n this.groupNameInputField = new InputField({\n label: 'CreateGroup.NameHolder',\n maxLength: 128\n });\n\n inputWrapper.append(this.groupNameInputField.container);\n\n this.groupNameInputField.input.addEventListener('input', () => {\n const value = this.groupNameInputField.value;\n this.nextBtn.classList.toggle('is-visible', !!value.length && !this.groupNameInputField.input.classList.contains('error'));\n });\n\n this.nextBtn = Button('btn-corner btn-circle', {icon: 'arrow_next'});\n\n this.nextBtn.addEventListener('click', () => {\n const title = this.groupNameInputField.value;\n\n this.nextBtn.disabled = true;\n appChatsManager.createChat(title, this.userIds).then((chatId) => {\n if(this.uploadAvatar) {\n this.uploadAvatar().then((inputFile) => {\n appChatsManager.editPhoto(chatId, inputFile);\n });\n }\n \n appSidebarLeft.removeTabFromHistory(this);\n appSidebarLeft.selectTab(0);\n });\n });\n\n const chatsContainer = document.createElement('div');\n chatsContainer.classList.add('chatlist-container');\n chatsContainer.append(this.searchGroup.container);\n\n this.content.append(this.nextBtn);\n this.scrollable.append(this.avatarEdit.container, inputWrapper, chatsContainer);\n }\n\n public onCloseAfterTimeout() {\n this.searchGroup.clear();\n this.avatarEdit.clear();\n this.uploadAvatar = null;\n this.groupNameInputField.value = '';\n this.nextBtn.disabled = false;\n }\n\n public open(userIds: number[]) {\n const result = super.open();\n result.then(() => {\n this.userIds = userIds;\n\n this.userIds.forEach(userId => {\n let {dom} = appDialogsManager.addDialogNew({\n dialog: userId,\n container: this.searchGroup.list,\n drawStatus: false,\n rippleEnabled: false,\n avatarSize: 48\n });\n\n dom.lastMessageSpan.append(appUsersManager.getUserStatusString(userId));\n });\n\n this.searchGroup.nameEl.textContent = '';\n this.searchGroup.nameEl.append(i18n('Members', [this.userIds.length]));\n this.searchGroup.setActive();\n });\n \n return result;\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport rootScope from \"../lib/rootScope\";\nimport appMessagesManager from \"../lib/appManagers/appMessagesManager\";\nimport appDocsManager, {MyDocument} from \"../lib/appManagers/appDocsManager\";\nimport { CancellablePromise, deferredPromise } from \"../helpers/cancellablePromise\";\nimport { isSafari } from \"../helpers/userAgent\";\nimport { MOUNT_CLASS_TO } from \"../config/debug\";\n\n// TODO: если удалить сообщение, и при этом аудио будет играть - оно не остановится, и можно будет по нему перейти вникуда\n\n// TODO: Safari: проверить стрим, включить его и сразу попробовать включить видео или другую песню\n// TODO: Safari: попробовать замаскировать подгрузку последнего чанка\n// TODO: Safari: пофиксить момент, когда заканчивается песня и пытаешься включить её заново - прогресс сразу в конце\n\ntype HTMLMediaElement = HTMLAudioElement | HTMLVideoElement;\n\ntype MediaType = 'voice' | 'audio' | 'round';\n\nclass AppMediaPlaybackController {\n private container: HTMLElement;\n private media: {\n [peerId: string]: {\n [mid: string]: HTMLMediaElement\n }\n } = {};\n private playingMedia: HTMLMediaElement;\n\n private waitingMediaForLoad: {\n [peerId: string]: {\n [mid: string]: CancellablePromise<void>\n }\n } = {};\n \n public willBePlayedMedia: HTMLMediaElement;\n\n private currentPeerId: number;\n private prevMid: number;\n private nextMid: number;\n\n constructor() {\n this.container = document.createElement('div');\n //this.container.style.cssText = 'position: absolute; top: -10000px; left: -10000px;';\n this.container.style.cssText = 'display: none;';\n document.body.append(this.container);\n }\n\n public addMedia(peerId: number, doc: MyDocument, mid: number, autoload = true): HTMLMediaElement {\n const storage = this.media[peerId] ?? (this.media[peerId] = {});\n if(storage[mid]) return storage[mid];\n\n const media = document.createElement(doc.type === 'round' ? 'video' : 'audio');\n //const source = document.createElement('source');\n //source.type = doc.type === 'voice' && !opusDecodeController.isPlaySupported() ? 'audio/wav' : doc.mime_type;\n\n if(doc.type === 'round') {\n media.setAttribute('playsinline', 'true');\n //media.muted = true;\n }\n\n media.dataset.mid = '' + mid;\n media.dataset.type = doc.type;\n \n //media.autoplay = true;\n media.volume = 1;\n //media.append(source);\n\n this.container.append(media);\n\n media.addEventListener('playing', () => {\n this.currentPeerId = peerId;\n\n //console.log('appMediaPlaybackController: video playing', this.currentPeerId, this.playingMedia, media);\n\n if(this.playingMedia !== media) {\n if(this.playingMedia && !this.playingMedia.paused) {\n this.playingMedia.pause();\n }\n \n this.playingMedia = media;\n this.loadSiblingsMedia(peerId, doc.type as MediaType, mid);\n }\n\n // audio_pause не успеет сработать без таймаута\n setTimeout(() => {\n rootScope.broadcast('audio_play', {peerId, doc, mid});\n }, 0);\n });\n\n media.addEventListener('pause', this.onPause);\n media.addEventListener('ended', this.onEnded);\n \n const onError = (e: Event) => {\n //console.log('appMediaPlaybackController: video onError', e);\n\n if(this.nextMid === mid) {\n this.loadSiblingsMedia(peerId, doc.type as MediaType, mid).then(() => {\n if(this.nextMid && storage[this.nextMid]) {\n storage[this.nextMid].play();\n }\n });\n }\n };\n\n media.addEventListener('error', onError);\n\n const deferred = deferredPromise<void>();\n if(autoload) {\n deferred.resolve();\n } else {\n const waitingStorage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});\n waitingStorage[mid] = deferred;\n }\n\n deferred.then(() => {\n //media.autoplay = true;\n //console.log('will set media url:', media, doc, doc.type, doc.url);\n\n ((!doc.supportsStreaming ? appDocsManager.downloadDoc(doc) : Promise.resolve()) as Promise<any>).then(() => {\n if(doc.type === 'audio' && doc.supportsStreaming && isSafari) {\n this.handleSafariStreamable(media);\n }\n \n media.src = doc.url;\n });\n }, onError);\n \n return storage[mid] = media;\n }\n\n // safari подгрузит последний чанк и песня включится,\n // при этом этот чанк нельзя руками отдать из SW, потому что браузер тогда теряется\n private handleSafariStreamable(media: HTMLMediaElement) {\n media.addEventListener('play', () => {\n /* if(media.readyState === 4) { // https://developer.mozilla.org/ru/docs/Web/API/XMLHttpRequest/readyState\n return;\n } */\n\n //media.volume = 0;\n const currentTime = media.currentTime;\n //this.setSafariBuffering(media, true);\n\n media.addEventListener('progress', () => {\n media.currentTime = media.duration - 1;\n\n media.addEventListener('progress', () => {\n media.currentTime = currentTime;\n //media.volume = 1;\n //this.setSafariBuffering(media, false);\n\n if(!media.paused) {\n media.play()/* .catch(() => {}) */;\n }\n }, {once: true});\n }, {once: true});\n }/* , {once: true} */);\n }\n\n public resolveWaitingForLoadMedia(peerId: number, mid: number) {\n const storage = this.waitingMediaForLoad[peerId] ?? (this.waitingMediaForLoad[peerId] = {});\n const promise = storage[mid];\n if(promise) {\n promise.resolve();\n delete storage[mid];\n }\n }\n \n /**\n * Only for audio\n */\n public isSafariBuffering(media: HTMLMediaElement) {\n /// @ts-ignore\n return !!media.safariBuffering;\n }\n\n private setSafariBuffering(media: HTMLMediaElement, value: boolean) {\n // @ts-ignore\n media.safariBuffering = value;\n }\n\n onPause = (e?: Event) => {\n /* const target = e.target as HTMLMediaElement;\n if(!isInDOM(target)) {\n this.container.append(target);\n target.play();\n return;\n } */\n\n rootScope.broadcast('audio_pause');\n };\n\n onEnded = (e?: Event) => {\n this.onPause(e);\n\n //console.log('on media end');\n\n if(this.nextMid) {\n const media = this.media[this.currentPeerId][this.nextMid];\n\n /* if(isSafari) {\n media.autoplay = true;\n } */\n\n this.resolveWaitingForLoadMedia(this.currentPeerId, this.nextMid);\n\n setTimeout(() => {\n media.play()//.catch(() => {});\n }, 0);\n }\n };\n\n private loadSiblingsMedia(peerId: number, type: MediaType, mid: number) {\n const media = this.playingMedia;\n this.prevMid = this.nextMid = 0;\n\n return appMessagesManager.getSearch({\n peerId, \n query: '', \n inputFilter: {\n //_: type === 'audio' ? 'inputMessagesFilterMusic' : (type === 'round' ? 'inputMessagesFilterRoundVideo' : 'inputMessagesFilterVoice')\n _: type === 'audio' ? 'inputMessagesFilterMusic' : 'inputMessagesFilterRoundVoice'\n },\n maxId: mid,\n limit: 3,\n backLimit: 2\n }).then(value => {\n if(this.playingMedia !== media) {\n return;\n }\n \n for(const {mid: m} of value.history) {\n if(m > mid) {\n this.nextMid = m;\n } else if(m < mid) {\n this.prevMid = m;\n break;\n }\n }\n\n [this.prevMid, this.nextMid].filter(Boolean).forEach(mid => {\n const message = appMessagesManager.getMessageByPeer(peerId, mid);\n this.addMedia(peerId, message.media.document, mid, false);\n });\n \n //console.log('loadSiblingsAudio', audio, type, mid, value, this.prevMid, this.nextMid);\n });\n }\n \n public toggle() {\n if(!this.playingMedia) return;\n\n if(this.playingMedia.paused) {\n this.playingMedia.play();\n } else {\n this.playingMedia.pause();\n }\n }\n\n public pause() {\n if(!this.playingMedia || this.playingMedia.paused) return;\n this.playingMedia.pause();\n }\n\n public willBePlayed(media: HTMLMediaElement) {\n this.willBePlayedMedia = media;\n }\n}\n\nconst appMediaPlaybackController = new AppMediaPlaybackController();\nMOUNT_CLASS_TO.appMediaPlaybackController = appMediaPlaybackController;\nexport default appMediaPlaybackController;\n","export type GrabEvent = {x: number, y: number, isTouch?: boolean};\n\nexport default function attachGrabListeners(element: HTMLElement, onStart: (position: GrabEvent) => void, onMove: (position: GrabEvent) => void, onEnd: (position: GrabEvent) => void) {\n // * Mouse\n const onMouseMove = (event: MouseEvent) => {\n onMove({x: event.pageX, y: event.pageY});\n };\n\n const onMouseUp = (event: MouseEvent) => {\n document.removeEventListener('mousemove', onMouseMove);\n element.addEventListener('mousedown', onMouseDown, {once: true});\n onEnd && onEnd({x: event.pageX, y: event.pageY});\n };\n\n const onMouseDown = (event: MouseEvent) => {\n if(event.button !== 0) {\n element.addEventListener('mousedown', onMouseDown, {once: true});\n return;\n }\n\n onStart({x: event.pageX, y: event.pageY});\n onMouseMove(event);\n\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp, {once: true});\n };\n\n element.addEventListener('mousedown', onMouseDown, {once: true});\n\n // * Touch\n const onTouchMove = (event: TouchEvent) => {\n event.preventDefault();\n onMove({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});\n };\n\n const onTouchEnd = (event: TouchEvent) => {\n document.removeEventListener('touchmove', onTouchMove);\n element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});\n onEnd && onEnd({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});\n };\n\n const onTouchStart = (event: TouchEvent) => {\n onStart({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});\n onTouchMove(event);\n\n document.addEventListener('touchmove', onTouchMove, {passive: false});\n document.addEventListener('touchend', onTouchEnd, {passive: true, once: true});\n };\n\n element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});\n\n return () => {\n element.removeEventListener('mousedown', onMouseDown);\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n\n element.removeEventListener('touchstart', onTouchStart);\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', onTouchEnd);\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { clamp } from \"../helpers/number\";\nimport attachGrabListeners, { GrabEvent } from \"../helpers/dom/attachGrabListeners\";\n\nexport default class RangeSelector {\n public container: HTMLDivElement;\n protected filled: HTMLDivElement;\n protected seek: HTMLInputElement;\n\n public mousedown = false;\n protected rect: DOMRect;\n protected _removeListeners: () => void;\n\n private events: Partial<{\n //onMouseMove: ProgressLine['onMouseMove'],\n onMouseDown: RangeSelector['onMouseDown'],\n onMouseUp: RangeSelector['onMouseUp'],\n onScrub: (value: number) => void\n }> = {};\n\n protected decimals: number;\n\n constructor(protected step: number, protected value: number, protected min: number, protected max: number) {\n this.container = document.createElement('div');\n this.container.classList.add('progress-line');\n\n this.filled = document.createElement('div');\n this.filled.classList.add('progress-line__filled');\n\n const seek = this.seek = document.createElement('input');\n seek.classList.add('progress-line__seek');\n //seek.setAttribute('max', '0');\n seek.type = 'range';\n seek.step = '' + step;\n seek.min = '' + this.min;\n seek.max = '' + this.max;\n seek.value = '' + value;\n\n if(value) {\n this.setProgress(value);\n }\n\n const stepStr = '' + this.step;\n const index = stepStr.indexOf('.');\n this.decimals = index === -1 ? 0 : stepStr.length - index - 1;\n\n //this.setListeners();\n\n this.container.append(this.filled, seek);\n }\n\n public setHandlers(events: RangeSelector['events']) {\n this.events = events;\n }\n\n protected onMouseMove = (event: GrabEvent) => {\n this.scrub(event);\n };\n\n protected onMouseDown = (event: GrabEvent) => {\n this.rect = this.container.getBoundingClientRect();\n this.mousedown = true;\n this.scrub(event);\n this.events?.onMouseDown && this.events.onMouseDown(event);\n };\n\n protected onMouseUp = (event: GrabEvent) => {\n this.mousedown = false;\n this.events?.onMouseUp && this.events.onMouseUp(event);\n };\n\n public setListeners() {\n this.seek.addEventListener('input', this.onInput);\n this._removeListeners = attachGrabListeners(this.container, this.onMouseDown, this.onMouseMove, this.onMouseUp);\n }\n\n public onInput = () => {\n const value = +this.seek.value;\n this.setFilled(value);\n this.events?.onScrub && this.events.onScrub(value);\n };\n\n public setProgress(value: number) {\n this.setFilled(value);\n this.seek.value = '' + value;\n }\n\n public setFilled(value: number) {\n let percents = (value - this.min) / (this.max - this.min);\n percents = clamp(percents, 0, 1);\n \n this.filled.style.width = (percents * 100) + '%';\n //this.filled.style.transform = 'scaleX(' + scaleX + ')';\n }\n\n protected scrub(event: GrabEvent) {\n const offsetX = clamp(event.x - this.rect.left, 0, this.rect.width);\n\n let value = this.min + (offsetX / this.rect.width * (this.max - this.min));\n\n if((value - this.min) < ((this.max - this.min) / 2)) {\n value -= this.step / 10;\n }\n \n value = +value.toFixed(this.decimals);\n value = clamp(value, this.min, this.max);\n\n //this.seek.value = '' + value;\n //this.onInput();\n\n this.setProgress(value);\n this.events?.onScrub && this.events.onScrub(value);\n\n return value;\n }\n\n public removeListeners() {\n if(this._removeListeners) {\n this._removeListeners();\n this._removeListeners = null;\n }\n\n this.seek.removeEventListener('input', this.onInput);\n \n this.events = {};\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { cancelEvent } from \"../helpers/dom\";\nimport appMediaPlaybackController from \"../components/appMediaPlaybackController\";\nimport { isAppleMobile } from \"../helpers/userAgent\";\nimport { isTouchSupported } from \"../helpers/touchSupport\";\nimport RangeSelector from \"../components/rangeSelector\";\nimport { onVideoLoad } from \"../helpers/files\";\n\nexport class MediaProgressLine extends RangeSelector {\n private filledLoad: HTMLDivElement;\n \n private stopAndScrubTimeout = 0;\n private progressRAF = 0;\n\n constructor(private media: HTMLAudioElement | HTMLVideoElement, private streamable = false) {\n super(1000 / 60 / 1000, 0, 0, 1);\n\n if(streamable) {\n this.filledLoad = document.createElement('div');\n this.filledLoad.classList.add('progress-line__filled', 'progress-line__loaded');\n this.container.prepend(this.filledLoad);\n //this.setLoadProgress();\n }\n\n if(!media.paused || media.currentTime > 0) {\n this.onPlay();\n }\n\n this.setSeekMax();\n this.setListeners();\n this.setHandlers({\n onMouseDown: () => {\n //super.onMouseDown(e);\n \n //Таймер для того, чтобы стопать видео, если зажал мышку и не отпустил клик\n if(this.stopAndScrubTimeout) { // возможно лишнее\n clearTimeout(this.stopAndScrubTimeout);\n }\n \n this.stopAndScrubTimeout = window.setTimeout(() => {\n !this.media.paused && this.media.pause();\n this.stopAndScrubTimeout = 0;\n }, 150);\n },\n\n onMouseUp: () => {\n //super.onMouseUp(e);\n \n if(this.stopAndScrubTimeout) {\n clearTimeout(this.stopAndScrubTimeout);\n this.stopAndScrubTimeout = 0;\n }\n \n this.media.paused && this.media.play();\n }\n })\n }\n\n onLoadedData = () => {\n this.max = this.media.duration;\n this.seek.setAttribute('max', '' + this.max);\n };\n\n onEnded = () => {\n this.setProgress();\n };\n\n onPlay = () => {\n let r = () => {\n this.setProgress();\n\n this.progressRAF = this.media.paused ? 0 : window.requestAnimationFrame(r);\n };\n\n if(this.progressRAF) {\n window.cancelAnimationFrame(this.progressRAF);\n }\n\n if(this.streamable) {\n this.setLoadProgress();\n }\n\n this.progressRAF = window.requestAnimationFrame(r);\n };\n\n onProgress = (e: Event) => {\n this.setLoadProgress();\n };\n\n protected scrub(e: MouseEvent) {\n const scrubTime = super.scrub(e);\n this.media.currentTime = scrubTime;\n return scrubTime;\n }\n\n protected setLoadProgress() {\n if(appMediaPlaybackController.isSafariBuffering(this.media)) return;\n const buf = this.media.buffered;\n const numRanges = buf.length;\n\n const currentTime = this.media.currentTime;\n let nearestStart = 0, end = 0;\n for(let i = 0; i < numRanges; ++i) {\n const start = buf.start(i);\n if(currentTime >= start && start >= nearestStart) {\n nearestStart = start;\n end = buf.end(i);\n }\n\n //console.log('onProgress range:', i, buf.start(i), buf.end(i), this.media);\n }\n\n //console.log('onProgress correct range:', nearestStart, end, this.media);\n\n const percents = this.media.duration ? end / this.media.duration : 0;\n this.filledLoad.style.width = (percents * 100) + '%';\n //this.filledLoad.style.transform = 'scaleX(' + percents + ')';\n }\n\n protected setSeekMax() {\n this.max = this.media.duration || 0;\n if(this.max > 0) {\n this.onLoadedData();\n } else {\n this.media.addEventListener('loadeddata', this.onLoadedData);\n }\n }\n\n public setProgress() {\n if(appMediaPlaybackController.isSafariBuffering(this.media)) return;\n const currentTime = this.media.currentTime;\n\n super.setProgress(currentTime);\n }\n\n public setListeners() {\n super.setListeners();\n this.media.addEventListener('ended', this.onEnded);\n this.media.addEventListener('play', this.onPlay);\n this.streamable && this.media.addEventListener('progress', this.onProgress);\n }\n\n public removeListeners() {\n super.removeListeners();\n\n this.media.removeEventListener('loadeddata', this.onLoadedData);\n this.media.removeEventListener('ended', this.onEnded);\n this.media.removeEventListener('play', this.onPlay);\n this.streamable && this.media.removeEventListener('progress', this.onProgress);\n\n if(this.stopAndScrubTimeout) {\n clearTimeout(this.stopAndScrubTimeout);\n }\n\n if(this.progressRAF) {\n window.cancelAnimationFrame(this.progressRAF);\n }\n }\n}\n\nlet lastVolume = 1, muted = !lastVolume;\nexport default class VideoPlayer {\n public wrapper: HTMLDivElement;\n public progress: MediaProgressLine;\n private skin: string;\n\n /* private videoParent: HTMLElement;\n private videoWhichChild: number; */\n\n constructor(public video: HTMLVideoElement, play = false, streamable = false, duration?: number) {\n this.wrapper = document.createElement('div');\n this.wrapper.classList.add('ckin__player');\n\n video.parentNode.insertBefore(this.wrapper, video);\n this.wrapper.appendChild(video);\n\n this.skin = video.dataset.ckin ?? 'default';\n\n this.stylePlayer(duration);\n\n if(this.skin === 'default') {\n let controls = this.wrapper.querySelector('.default__controls.ckin__controls') as HTMLDivElement;\n this.progress = new MediaProgressLine(video, streamable);\n controls.prepend(this.progress.container);\n }\n\n if(play/* && video.paused */) {\n const promise = video.play();\n promise.catch((err: Error) => {\n if(err.name === 'NotAllowedError') {\n video.muted = true;\n video.autoplay = true;\n video.play();\n }\n }).finally(() => { // due to autoplay, play will not call\n this.wrapper.classList.toggle('is-playing', !this.video.paused);\n });\n //(this.wrapper.querySelector('.toggle') as HTMLButtonElement).click();\n }\n }\n\n private stylePlayer(initDuration: number) {\n const {wrapper: player, video, skin} = this;\n\n player.classList.add(skin);\n \n const html = this.buildControls();\n player.insertAdjacentHTML('beforeend', html);\n let timeDuration: HTMLElement;\n \n if(skin === 'default') {\n const toggle = player.querySelectorAll('.toggle') as NodeListOf<HTMLElement>;\n const fullScreenButton = player.querySelector('.fullscreen') as HTMLElement;\n const timeElapsed = player.querySelector('#time-elapsed');\n timeDuration = player.querySelector('#time-duration') as HTMLElement;\n timeDuration.innerHTML = String(video.duration | 0).toHHMMSS();\n\n const volumeDiv = document.createElement('div');\n volumeDiv.classList.add('player-volume');\n\n volumeDiv.innerHTML = `\n <svg class=\"player-volume__icon\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"></svg>\n `;\n const volumeSvg = volumeDiv.firstElementChild as SVGSVGElement;\n\n volumeSvg.addEventListener('click', (e) => {\n cancelEvent(e);\n video.muted = !video.muted;\n });\n\n const volumeProgress = new RangeSelector(0.01, 1, 0, 1);\n volumeProgress.setListeners();\n volumeProgress.setHandlers({\n onScrub: currentTime => {\n const value = Math.max(Math.min(currentTime, 1), 0);\n\n //console.log('volume scrub:', currentTime, value);\n\n video.muted = false;\n video.volume = value;\n }\n });\n volumeDiv.append(volumeProgress.container);\n\n const setVolume = () => {\n const volume = video.volume;\n let d: string;\n if(!volume || video.muted) {\n d = `M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z`;\n } else if(volume > .5) {\n d = `M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z`;\n } else if(volume > 0 && volume < .25) {\n d = `M7 9v6h4l5 5V4l-5 5H7z`;\n } else {\n d = `M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z`;\n }\n\n try {\n volumeSvg.innerHTML = `<path d=\"${d}\"></path>`;\n } catch(err) {}\n\n if(!volumeProgress.mousedown) {\n volumeProgress.setProgress(video.muted ? 0 : volume);\n }\n };\n \n // не вызовется повторно если на 1 установить 1\n video.addEventListener('volumechange', () => {\n muted = video.muted;\n lastVolume = video.volume;\n setVolume();\n });\n\n video.volume = lastVolume;\n video.muted = muted;\n\n setVolume();\n\n // volume end\n\n const leftControls = player.querySelector('.left-controls');\n leftControls.insertBefore(volumeDiv, timeElapsed.parentElement);\n\n Array.from(toggle).forEach((button) => {\n return button.addEventListener('click', () => {\n this.togglePlay();\n });\n });\n\n video.addEventListener('click', () => {\n if(!isTouchSupported) {\n this.togglePlay();\n return;\n }\n });\n\n if(isTouchSupported) {\n let showControlsTimeout = 0;\n\n const t = () => {\n showControlsTimeout = window.setTimeout(() => {\n showControlsTimeout = 0;\n player.classList.remove('show-controls');\n }, 3e3);\n };\n\n player.addEventListener('click', () => {\n if(showControlsTimeout) {\n clearTimeout(showControlsTimeout);\n } else {\n player.classList.add('show-controls');\n }\n \n t();\n });\n\n player.addEventListener('touchstart', () => {\n player.classList.add('show-controls');\n clearTimeout(showControlsTimeout);\n });\n\n player.addEventListener('touchend', () => {\n if(player.classList.contains('is-playing')) {\n t();\n }\n });\n }\n \n /* player.addEventListener('click', (e) => {\n if(e.target !== player) {\n return;\n }\n\n this.togglePlay();\n }); */\n \n /* video.addEventListener('play', () => {\n }); */\n\n video.addEventListener('dblclick', () => {\n if(isTouchSupported) {\n return;\n }\n\n return this.toggleFullScreen(fullScreenButton);\n })\n\n fullScreenButton.addEventListener('click', (e) => {\n return this.toggleFullScreen(fullScreenButton);\n });\n\n 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange'.split(' ').forEach(eventName => {\n player.addEventListener(eventName, this.onFullScreen, false);\n });\n\n video.addEventListener('timeupdate', () => {\n timeElapsed.innerHTML = String(video.currentTime | 0).toHHMMSS();\n });\n }\n\n video.addEventListener('play', () => {\n this.wrapper.classList.add('is-playing');\n });\n\n video.addEventListener('pause', () => {\n this.wrapper.classList.remove('is-playing');\n });\n \n if(video.duration || initDuration) {\n timeDuration.innerHTML = String(Math.round(video.duration || initDuration)).toHHMMSS();\n } else {\n onVideoLoad(video).then(() => {\n timeDuration.innerHTML = String(Math.round(video.duration)).toHHMMSS();\n });\n }\n }\n\n public togglePlay(stop?: boolean) {\n //console.log('video togglePlay:', stop, this.video.paused);\n\n if(stop) {\n this.video.pause();\n this.wrapper.classList.remove('is-playing');\n return;\n } else if(stop === false) {\n this.video.play();\n this.wrapper.classList.add('is-playing');\n return;\n }\n \n this.video[this.video.paused ? 'play' : 'pause']();\n //this.wrapper.classList.toggle('is-playing', !this.video.paused);\n }\n\n private buildControls() {\n const skin = this.skin;\n if(skin === 'default') {\n return `\n <button class=\"${skin}__button--big toggle tgico\" title=\"Toggle Play\"></button>\n <div class=\"${skin}__gradient-bottom ckin__controls\"></div>\n <div class=\"${skin}__controls ckin__controls\">\n <div class=\"bottom-controls\">\n <div class=\"left-controls\">\n <button class=\"${skin}__button toggle tgico\" title=\"Toggle Video\"></button>\n <div class=\"time\">\n <time id=\"time-elapsed\">0:00</time>\n <span> / </span>\n <time id=\"time-duration\">0:00</time>\n </div>\n </div>\n <div class=\"right-controls\">\n <button class=\"${skin}__button fullscreen tgico-fullscreen\" title=\"Full Screen\"></button>\n </div>\n </div>\n </div>`;\n }\n }\n\n public static isFullScreen(): boolean {\n // @ts-ignore\n return !!(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);\n }\n \n public toggleFullScreen(fullScreenButton: HTMLElement) {\n // alternative standard method\n const player = this.wrapper;\n\n // * https://caniuse.com/#feat=fullscreen\n if(isAppleMobile) {\n const video = this.video as any;\n video.webkitEnterFullscreen();\n video.enterFullscreen();\n return;\n }\n \n if(!VideoPlayer.isFullScreen()) {\n player.classList.add('ckin__fullscreen');\n\n /* const videoParent = this.video.parentElement;\n const videoWhichChild = whichChild(this.video);\n const needVideoRemount = videoParent !== player;\n\n if(needVideoRemount) {\n this.videoParent = videoParent;\n this.videoWhichChild = videoWhichChild;\n player.prepend(this.video);\n } */\n \n if(player.requestFullscreen) {\n player.requestFullscreen();\n // @ts-ignore\n } else if(player.mozRequestFullScreen) {\n // @ts-ignore\n player.mozRequestFullScreen(); // Firefox\n // @ts-ignore\n } else if(player.webkitRequestFullscreen) {\n // @ts-ignore\n player.webkitRequestFullscreen(); // Chrome and Safari\n // @ts-ignore\n } else if(player.msRequestFullscreen) {\n // @ts-ignore\n player.msRequestFullscreen();\n }\n \n fullScreenButton.classList.remove('tgico-fullscreen');\n fullScreenButton.classList.add('tgico-smallscreen');\n fullScreenButton.setAttribute('title', 'Exit Full Screen');\n } else {\n player.classList.remove('ckin__fullscreen');\n\n /* if(this.videoParent) {\n const {videoWhichChild, videoParent} = this;\n if(!videoWhichChild) {\n videoParent.prepend(this.video);\n } else {\n videoParent.insertBefore(this.video, videoParent.children[videoWhichChild]);\n }\n\n this.videoParent = null;\n this.videoWhichChild = -1;\n } */\n \n // @ts-ignore\n if(document.cancelFullScreen) {\n // @ts-ignore\n document.cancelFullScreen();\n // @ts-ignore\n } else if(document.mozCancelFullScreen) {\n // @ts-ignore\n document.mozCancelFullScreen();\n // @ts-ignore\n } else if(document.webkitCancelFullScreen) {\n // @ts-ignore\n document.webkitCancelFullScreen();\n // @ts-ignore\n } else if(document.msExitFullscreen) {\n // @ts-ignore\n document.msExitFullscreen();\n }\n \n fullScreenButton.classList.remove('tgico-smallscreen');\n fullScreenButton.classList.add('tgico-fullscreen');\n fullScreenButton.setAttribute('title', 'Full Screen');\n }\n }\n \n onFullScreen = () => {\n // @ts-ignore\n const isFullscreenNow = document.webkitFullscreenElement !== null;\n if(!isFullscreenNow) {\n this.wrapper.classList.remove('ckin__fullscreen');\n } else {\n }\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDocsManager, {MyDocument} from \"../lib/appManagers/appDocsManager\";\nimport { RichTextProcessor } from \"../lib/richtextprocessor\";\nimport { formatDate } from \"./wrappers\";\nimport ProgressivePreloader from \"./preloader\";\nimport { MediaProgressLine } from \"../lib/mediaPlayer\";\nimport appMediaPlaybackController from \"./appMediaPlaybackController\";\nimport { DocumentAttribute } from \"../layer\";\nimport mediaSizes from \"../helpers/mediaSizes\";\nimport { isSafari } from \"../helpers/userAgent\";\nimport appMessagesManager from \"../lib/appManagers/appMessagesManager\";\nimport rootScope from \"../lib/rootScope\";\nimport './middleEllipsis';\nimport { attachClickEvent, cancelEvent, detachClickEvent } from \"../helpers/dom\";\nimport { SearchSuperContext } from \"./appSearchSuper.\";\nimport { formatDateAccordingToToday } from \"../helpers/date\";\n\nrootScope.on('messages_media_read', e => {\n const {mids, peerId} = e;\n\n mids.forEach(mid => {\n (Array.from(document.querySelectorAll('audio-element[message-id=\"' + mid + '\"][peer-id=\"' + peerId + '\"]')) as AudioElement[]).forEach(elem => {\n //console.log('updating avatar:', elem);\n elem.classList.remove('is-unread');\n });\n });\n});\n\n// https://github.com/LonamiWebs/Telethon/blob/4393ec0b83d511b6a20d8a20334138730f084375/telethon/utils.py#L1285\nexport function decodeWaveform(waveform: Uint8Array | number[]) {\n if(!(waveform instanceof Uint8Array)) {\n waveform = new Uint8Array(waveform);\n }\n\n const bitCount = waveform.length * 8;\n const valueCount = bitCount / 5 | 0;\n if(!valueCount) {\n return new Uint8Array([]);\n }\n\n let result: Uint8Array;\n try {\n const dataView = new DataView(waveform.buffer);\n result = new Uint8Array(valueCount);\n for(let i = 0; i < valueCount; i++) {\n const byteIndex = i * 5 / 8 | 0;\n const bitShift = i * 5 % 8;\n const value = dataView.getUint16(byteIndex, true);\n result[i] = (value >> bitShift) & 0b00011111;\n }\n } catch(err) {\n result = new Uint8Array([]);\n }\n\n /* var byteIndex = (valueCount - 1) / 8 | 0;\n var bitShift = (valueCount - 1) % 8;\n if(byteIndex === waveform.length - 1) {\n var value = waveform[byteIndex];\n } else {\n var value = dataView.getUint16(byteIndex, true);\n }\n console.log('decoded waveform, setting last value:', value, byteIndex, bitShift);\n result[valueCount - 1] = (value >> bitShift) & 0b00011111; */\n return result;\n}\n\nfunction wrapVoiceMessage(audioEl: AudioElement) {\n audioEl.classList.add('is-voice');\n\n const message = audioEl.message;\n const doc = (message.media.document || message.media.webpage.document) as MyDocument;\n const isOut = message.fromId === rootScope.myId && message.peerId !== rootScope.myId;\n let isUnread = message && message.pFlags.media_unread;\n if(isUnread) {\n audioEl.classList.add('is-unread');\n }\n\n if(message.pFlags.out) {\n audioEl.classList.add('is-out');\n }\n\n const barWidth = 2;\n const barMargin = 2; //mediaSizes.isMobile ? 2 : 1;\n const barHeightMin = 4; //mediaSizes.isMobile ? 3 : 2;\n const barHeightMax = mediaSizes.isMobile ? 16 : 23;\n const availW = 150; //mediaSizes.isMobile ? 152 : 190;\n\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.classList.add('audio-waveform');\n svg.setAttributeNS(null, 'width', '' + availW);\n svg.setAttributeNS(null, 'height', '' + barHeightMax);\n svg.setAttributeNS(null, 'viewBox', `0 0 ${availW} ${barHeightMax}`);\n\n const timeDiv = document.createElement('div');\n timeDiv.classList.add('audio-time');\n audioEl.append(svg, timeDiv);\n\n let waveform = (doc.attributes.find(attribute => attribute._ === 'documentAttributeAudio') as DocumentAttribute.documentAttributeAudio).waveform || new Uint8Array([]);\n waveform = decodeWaveform(waveform.slice(0, 63));\n\n //console.log('decoded waveform:', waveform);\n\n const normValue = Math.max(...waveform);\n const wfSize = waveform.length ? waveform.length : 100;\n const barCount = Math.min((availW / (barWidth + barMargin)) | 0, wfSize);\n\n let maxValue = 0;\n const maxDelta = barHeightMax - barHeightMin;\n\n let html = '';\n for(let i = 0, barX = 0, sumI = 0; i < wfSize; ++i) {\n const value = waveform[i] || 0;\n if((sumI + barCount) >= wfSize) { // draw bar\n sumI = sumI + barCount - wfSize;\n\t\t\tif(sumI < (barCount + 1) / 2) {\n\t\t\t\tif(maxValue < value) maxValue = value;\n }\n \n const bar_value = Math.max(((maxValue * maxDelta) + ((normValue + 1) / 2)) / (normValue + 1), barHeightMin);\n \n const h = `\n <rect x=\"${barX}\" y=\"${barHeightMax - bar_value}\" width=\"${barWidth}\" height=\"${bar_value}\" rx=\"1\" ry=\"1\"></rect>\n `;\n html += h;\n\n barX += barWidth + barMargin;\n\n if(sumI < (barCount + 1) / 2) {\n maxValue = 0;\n } else {\n maxValue = value;\n }\n } else {\n if(maxValue < value) maxValue = value;\n\n sumI += barCount;\n }\n }\n\n svg.insertAdjacentHTML('beforeend', html);\n const rects = Array.from(svg.children) as HTMLElement[];\n\n let progress = audioEl.querySelector('.audio-waveform') as HTMLDivElement;\n \n const onLoad = () => {\n let interval = 0;\n let lastIndex = 0;\n\n let audio = audioEl.audio;\n\n if(!audio.paused || (audio.currentTime > 0 && audio.currentTime !== audio.duration)) {\n lastIndex = Math.round(audio.currentTime / audio.duration * barCount);\n rects.slice(0, lastIndex + 1).forEach(node => node.classList.add('active'));\n }\n\n let start = () => {\n clearInterval(interval);\n interval = window.setInterval(() => {\n if(lastIndex > svg.childElementCount || isNaN(audio.duration) || audio.paused) {\n clearInterval(interval);\n return;\n }\n\n lastIndex = Math.round(audio.currentTime / audio.duration * barCount);\n \n //svg.children[lastIndex].setAttributeNS(null, 'fill', '#000');\n //svg.children[lastIndex].classList.add('active'); #Иногда пропускает полоски..\n rects.slice(0, lastIndex + 1).forEach(node => node.classList.add('active'));\n //++lastIndex;\n //console.log('lastIndex:', lastIndex, audio.currentTime);\n //}, duration * 1000 / svg.childElementCount | 0/* 63 * duration / 10 */);\n }, 20);\n };\n\n if(!audio.paused) {\n start();\n }\n\n audioEl.addAudioListener('playing', () => {\n if(isUnread && !isOut && audioEl.classList.contains('is-unread')) {\n audioEl.classList.remove('is-unread');\n appMessagesManager.readMessages(audioEl.message.peerId, [audioEl.message.mid]);\n isUnread = false;\n }\n\n //rects.forEach(node => node.classList.remove('active'));\n start();\n });\n\n audioEl.addAudioListener('pause', () => {\n clearInterval(interval);\n });\n \n audioEl.addAudioListener('ended', () => {\n clearInterval(interval);\n rects.forEach(node => node.classList.remove('active'));\n });\n \n let mousedown = false, mousemove = false;\n progress.addEventListener('mouseleave', (e) => {\n if(mousedown) {\n audio.play();\n mousedown = false;\n }\n mousemove = false;\n })\n progress.addEventListener('mousemove', (e) => {\n mousemove = true;\n if(mousedown) scrub(e);\n });\n progress.addEventListener('mousedown', (e) => {\n e.preventDefault();\n if(!audio.paused) {\n audio.pause();\n }\n \n scrub(e);\n mousedown = true;\n });\n progress.addEventListener('mouseup', (e) => {\n if (mousemove && mousedown) {\n audio.play();\n mousedown = false;\n }\n });\n attachClickEvent(progress, (e) => {\n cancelEvent(e);\n if(!audio.paused) scrub(e);\n });\n \n function scrub(e: MouseEvent | TouchEvent) {\n let offsetX: number;\n if(e instanceof MouseEvent) {\n offsetX = e.offsetX;\n } else { // touch\n const rect = (e.target as HTMLElement).getBoundingClientRect();\n offsetX = e.targetTouches[0].pageX - rect.left;\n }\n \n const scrubTime = offsetX / availW /* width */ * audio.duration;\n lastIndex = Math.round(scrubTime / audio.duration * barCount);\n \n rects.slice(0, lastIndex + 1).forEach(node => node.classList.add('active'));\n for(let i = lastIndex + 1; i < rects.length; ++i) {\n rects[i].classList.remove('active')\n }\n audio.currentTime = scrubTime;\n }\n \n return () => {\n clearInterval(interval);\n progress.remove();\n progress = null;\n audio = null;\n };\n };\n\n return onLoad;\n}\n\nfunction wrapAudio(audioEl: AudioElement) {\n const withTime = audioEl.withTime;\n\n const message = audioEl.message;\n const doc: MyDocument = message.media.document || message.media.webpage.document;\n\n const senderTitle = audioEl.showSender ? appMessagesManager.getSenderToPeerText(message) : '';\n\n let title = doc.type === 'voice' ? senderTitle : (doc.audioTitle || doc.file_name);\n let subtitle: string;\n \n if(doc.type === 'voice') {\n subtitle = '';\n } else {\n subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : '';\n if(withTime) {\n subtitle += (subtitle ? ' • ' : '') + formatDate(doc.date);\n } else if(!subtitle) {\n subtitle = 'Unknown Artist';\n }\n\n if(audioEl.showSender) {\n subtitle += ' • ' + senderTitle;\n } else {\n subtitle = ' • ' + subtitle;\n }\n }\n\n let titleAdditionHTML = '';\n if(audioEl.showSender) {\n titleAdditionHTML = `<div class=\"sent-time\">${formatDateAccordingToToday(new Date(message.date * 1000))}</div>`;\n }\n\n const html = `\n <div class=\"audio-details\">\n <div class=\"audio-title\"><middle-ellipsis-element data-font-weight=\"${audioEl.dataset.fontWeight}\">${title}</middle-ellipsis-element>${titleAdditionHTML}</div>\n <div class=\"audio-subtitle\"><div class=\"audio-time\"></div>${subtitle || '<div></div>'}</div>\n </div>`;\n \n audioEl.insertAdjacentHTML('beforeend', html);\n\n const onLoad = () => {\n const subtitleDiv = audioEl.querySelector('.audio-subtitle') as HTMLDivElement;\n let launched = false;\n\n let progressLine = new MediaProgressLine(audioEl.audio, doc.supportsStreaming);\n\n audioEl.addAudioListener('ended', () => {\n audioEl.classList.remove('audio-show-progress');\n // Reset subtitle\n subtitleDiv.lastChild.replaceWith(subtitle);\n launched = false;\n });\n\n const onPlaying = () => {\n if(!launched) {\n audioEl.classList.add('audio-show-progress');\n launched = true;\n\n if(progressLine) {\n subtitleDiv.lastChild.replaceWith(progressLine.container);\n }\n }\n };\n\n audioEl.addAudioListener('playing', onPlaying);\n\n if(!audioEl.audio.paused || audioEl.audio.currentTime > 0) {\n onPlaying();\n }\n\n return () => {\n progressLine.removeListeners();\n progressLine.container.remove();\n progressLine = null;\n };\n };\n\n return onLoad;\n}\n\nexport default class AudioElement extends HTMLElement {\n public audio: HTMLAudioElement;\n public preloader: ProgressivePreloader;\n public message: any;\n public withTime = false;\n public voiceAsMusic = false;\n public searchContext: SearchSuperContext;\n public showSender = false;\n public noAutoDownload: boolean;\n\n private attachedHandlers: {[name: string]: any[]} = {};\n private onTypeDisconnect: () => void;\n public onLoad: (autoload?: boolean) => void;\n\n constructor() {\n super();\n // элемент создан\n }\n\n public render() {\n this.classList.add('audio');\n\n const doc = this.message.media.document || this.message.media.webpage.document;\n const isRealVoice = doc.type === 'voice';\n const isVoice = !this.voiceAsMusic && isRealVoice;\n const isOutgoing = this.message.pFlags.is_outgoing;\n const uploading = isOutgoing && this.preloader;\n\n const durationStr = String(doc.duration | 0).toHHMMSS();\n\n this.innerHTML = `<div class=\"audio-toggle audio-ico\"> \n <div class=\"part one\" x=\"0\" y=\"0\" fill=\"#fff\"></div>\n <div class=\"part two\" x=\"0\" y=\"0\" fill=\"#fff\"></div>\n </div>`;\n\n const downloadDiv = document.createElement('div');\n downloadDiv.classList.add('audio-download');\n\n if(uploading) {\n this.append(downloadDiv);\n }\n\n const onTypeLoad = isVoice ? wrapVoiceMessage(this) : wrapAudio(this);\n \n const audioTimeDiv = this.querySelector('.audio-time') as HTMLDivElement;\n audioTimeDiv.innerHTML = durationStr;\n\n const onLoad = this.onLoad = (autoload = true) => {\n this.onLoad = undefined;\n\n const audio = this.audio = appMediaPlaybackController.addMedia(this.message.peerId, this.message.media.document || this.message.media.webpage.document, this.message.mid, autoload);\n\n this.onTypeDisconnect = onTypeLoad();\n \n const toggle = this.querySelector('.audio-toggle') as HTMLDivElement;\n\n const getTimeStr = () => String(audio.currentTime | 0).toHHMMSS() + (isVoice ? (' / ' + durationStr) : '');\n\n const onPlaying = () => {\n audioTimeDiv.innerText = getTimeStr();\n toggle.classList.toggle('playing', !audio.paused);\n };\n\n if(!audio.paused || (audio.currentTime > 0 && audio.currentTime !== audio.duration)) {\n onPlaying();\n }\n\n attachClickEvent(toggle, (e) => {\n cancelEvent(e);\n if(audio.paused) audio.play().catch(() => {});\n else audio.pause();\n });\n\n this.addAudioListener('ended', () => {\n toggle.classList.remove('playing');\n });\n\n this.addAudioListener('timeupdate', () => {\n if(appMediaPlaybackController.isSafariBuffering(audio)) return;\n audioTimeDiv.innerText = getTimeStr();\n });\n\n this.addAudioListener('pause', () => {\n toggle.classList.remove('playing');\n });\n\n this.addAudioListener('playing', onPlaying);\n };\n\n if(!isOutgoing) {\n let preloader: ProgressivePreloader = this.preloader;\n\n const getDownloadPromise = () => appDocsManager.downloadDoc(doc);\n\n if(isRealVoice) {\n if(!preloader) {\n preloader = new ProgressivePreloader({\n cancelable: true\n });\n }\n\n const load = () => {\n const download = getDownloadPromise();\n preloader.attach(downloadDiv, false, download);\n\n if(!downloadDiv.parentElement) {\n this.append(downloadDiv);\n }\n\n (download as Promise<any>).then(() => {\n detachClickEvent(this, onClick);\n onLoad();\n\n downloadDiv.classList.add('downloaded');\n setTimeout(() => {\n downloadDiv.remove();\n }, 200);\n });\n\n return {download};\n };\n\n preloader.construct();\n preloader.setManual();\n preloader.attach(downloadDiv);\n preloader.setDownloadFunction(load);\n\n const onClick = (e?: Event) => {\n preloader.onClick(e);\n };\n \n attachClickEvent(this, onClick);\n\n if(!this.noAutoDownload) {\n onClick();\n }\n } else {\n if(doc.supportsStreaming) {\n onLoad(false);\n }\n\n //if(appMediaPlaybackController.mediaExists(mid)) { // чтобы показать прогресс, если аудио уже было скачано\n //onLoad();\n //} else {\n const r = (e: Event) => {\n if(!this.audio) {\n onLoad(false);\n }\n\n if(this.audio.src) {\n return;\n }\n //onLoad();\n //cancelEvent(e);\n appMediaPlaybackController.resolveWaitingForLoadMedia(this.message.peerId, this.message.mid);\n \n appMediaPlaybackController.willBePlayed(this.audio); // prepare for loading audio\n \n if(!preloader) {\n if(doc.supportsStreaming) {\n preloader = new ProgressivePreloader({\n cancelable: false\n });\n\n preloader.attach(downloadDiv, false);\n } else {\n preloader = new ProgressivePreloader({\n cancelable: true\n });\n\n const load = () => {\n const download = getDownloadPromise();\n preloader.attach(downloadDiv, false, download);\n return {download};\n };\n\n preloader.setDownloadFunction(load);\n load();\n }\n }\n\n if(isSafari) {\n this.audio.autoplay = true;\n this.audio.play().catch(() => {});\n }\n\n this.append(downloadDiv);\n \n new Promise<void>((resolve) => {\n if(this.audio.readyState >= 2) resolve();\n else this.addAudioListener('canplay', resolve);\n }).then(() => {\n downloadDiv.classList.add('downloaded');\n setTimeout(() => {\n downloadDiv.remove();\n }, 200);\n \n //setTimeout(() => {\n // release loaded audio\n if(appMediaPlaybackController.willBePlayedMedia === this.audio) {\n this.audio.play();\n appMediaPlaybackController.willBePlayedMedia = null;\n }\n //}, 10e3);\n });\n };\n\n if(!this.audio?.src) {\n attachClickEvent(this, r, {once: true, capture: true, passive: false});\n }\n //}\n }\n } else if(uploading) {\n this.preloader.attach(downloadDiv, false);\n //onLoad();\n }\n }\n\n /* connectedCallback() {\n // браузер вызывает этот метод при добавлении элемента в документ\n // (может вызываться много раз, если элемент многократно добавляется/удаляется)\n } */\n\n public addAudioListener(name: string, callback: any) {\n if(!this.attachedHandlers[name]) this.attachedHandlers[name] = [];\n this.attachedHandlers[name].push(callback);\n this.audio.addEventListener(name, callback);\n }\n\n disconnectedCallback() {\n if(this.isConnected) {\n return;\n }\n \n // браузер вызывает этот метод при удалении элемента из документа\n // (может вызываться много раз, если элемент многократно добавляется/удаляется)\n if(this.onTypeDisconnect) {\n this.onTypeDisconnect();\n this.onTypeDisconnect = null;\n }\n\n for(let name in this.attachedHandlers) {\n for(let callback of this.attachedHandlers[name]) {\n this.audio.removeEventListener(name, callback);\n }\n \n delete this.attachedHandlers[name];\n }\n\n this.preloader = null;\n }\n}\n\ncustomElements.define(\"audio-element\", AudioElement);\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport default class DivAndCaption<T> {\n public container: HTMLElement;\n public border: HTMLElement;\n public content: HTMLElement;\n public title: HTMLElement;\n public subtitle: HTMLElement;\n\n constructor(protected className: string, public fill?: T) {\n this.container = document.createElement('div');\n this.container.className = className;\n\n this.border = document.createElement('div');\n this.border.classList.add(className + '-border');\n \n this.content = document.createElement('div');\n this.content.classList.add(className + '-content');\n\n this.title = document.createElement('div');\n this.title.classList.add(className + '-title');\n\n this.subtitle = document.createElement('div');\n this.subtitle.classList.add(className + '-subtitle');\n\n this.content.append(this.title, this.subtitle);\n this.container.append(this.border, this.content);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport renderImageFromUrl from \"../../helpers/dom/renderImageFromUrl\";\nimport { limitSymbols } from \"../../helpers/string\";\nimport appImManager, { CHAT_ANIMATION_GROUP } from \"../../lib/appManagers/appImManager\";\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport appPhotosManager from \"../../lib/appManagers/appPhotosManager\";\nimport { RichTextProcessor } from \"../../lib/richtextprocessor\";\nimport DivAndCaption from \"../divAndCaption\";\nimport { wrapSticker } from \"../wrappers\";\n\nexport function wrapReplyDivAndCaption(options: {\n title: string,\n titleEl: HTMLElement,\n subtitle: string,\n subtitleEl: HTMLElement,\n message: any,\n mediaEl: HTMLElement\n}) {\n let {title, titleEl, subtitle, subtitleEl, mediaEl, message} = options;\n if(title !== undefined) {\n limitSymbols(title, 140);\n\n title = title ? RichTextProcessor.wrapEmojiText(title) : '';\n titleEl.innerHTML = title;\n }\n\n let media = message && message.media;\n let setMedia = false;\n if(media && mediaEl) {\n subtitleEl.textContent = '';\n subtitleEl.append(appMessagesManager.wrapMessageForReply(message));\n\n //console.log('wrap reply', media);\n\n if(media.webpage) {\n media = media.webpage;\n }\n \n if(media.photo || (media.document && ['video', 'sticker', 'gif'].indexOf(media.document.type) !== -1)) {\n /* const middlewareOriginal = appImManager.chat.bubbles.getMiddleware();\n const middleware = () => {\n \n }; */\n\n const boxSize = 32;\n if(media.document?.type === 'sticker') {\n if(mediaEl.style.backgroundImage) {\n mediaEl.style.backgroundImage = ''; \n }\n\n setMedia = true;\n wrapSticker({\n doc: media.document,\n div: mediaEl,\n lazyLoadQueue: appImManager.chat.bubbles.lazyLoadQueue,\n group: CHAT_ANIMATION_GROUP,\n //onlyThumb: media.document.sticker === 2,\n width: boxSize,\n height: boxSize\n });\n } else {\n if(mediaEl.firstElementChild) {\n mediaEl.innerHTML = '';\n }\n\n const photo = media.photo || media.document;\n\n const cacheContext = appPhotosManager.getCacheContext(photo);\n\n if(!cacheContext.downloaded) {\n const sizes = photo.sizes || photo.thumbs;\n if(sizes && sizes[0].bytes) {\n setMedia = true;\n renderImageFromUrl(mediaEl, appPhotosManager.getPreviewURLFromThumb(sizes[0]));\n }\n }\n\n const size = appPhotosManager.choosePhotoSize(photo, boxSize, boxSize/* mediaSizes.active.regular.width, mediaSizes.active.regular.height */);\n if(size._ !== 'photoSizeEmpty') {\n setMedia = true;\n appPhotosManager.preloadPhoto(photo, size)\n .then(() => {\n renderImageFromUrl(mediaEl, photo._ === 'photo' ? photo.url : appPhotosManager.getDocumentCachedThumb(photo.id).url);\n });\n }\n }\n }\n } else {\n subtitle = limitSymbols(subtitle, 140);\n subtitle = subtitle ? RichTextProcessor.wrapEmojiText(subtitle) : '';\n subtitleEl.innerHTML = subtitle;\n }\n \n return setMedia;\n}\n\nexport default class ReplyContainer extends DivAndCaption<(title: string, subtitle: string, message?: any) => void> {\n private mediaEl: HTMLElement;\n\n constructor(protected className: string) {\n super(className, (title: string, subtitle: string = '', message?: any) => {\n if(!this.mediaEl) {\n this.mediaEl = document.createElement('div');\n this.mediaEl.classList.add(this.className + '-media');\n }\n\n const isMediaSet = wrapReplyDivAndCaption({\n title,\n titleEl: this.title,\n subtitle,\n subtitleEl: this.subtitle,\n mediaEl: this.mediaEl,\n message\n });\n \n this.container.classList.toggle('is-media', isMediaSet);\n if(isMediaSet) {\n this.content.prepend(this.mediaEl);\n } else {\n this.mediaEl.remove();\n }\n });\n }\n}","/*\nThis file is part of Telegram Desktop,\nthe official desktop application for the Telegram messaging service.\nFor license and copyright information please follow this link:\nhttps://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n*/\n\nimport { accumulate } from \"../helpers/array\";\nimport { clamp } from \"../helpers/number\";\n\ntype Size = {w: number, h: number};\nexport type GroupMediaLayout = {\n geometry: {\n x: number,\n y: number,\n width: number,\n height: number\n },\n sides: number\n};\ntype Attempt = {\n lineCounts: number[],\n heights: number[]\n};\nexport const RectPart = {\n None: 0,\n Top: 1,\n Right: 2,\n Bottom: 4,\n Left: 8\n};\n\n// https://github.com/telegramdesktop/tdesktop/blob/4669c07dc5335cbf4795bbbe5b0ab7c007b9aee2/Telegram/SourceFiles/ui/grouped_layout.cpp\nexport class Layouter {\n private count: number;\n private ratios: number[];\n private proportions: string;\n private averageRatio: number;\n private maxSizeRatio: number;\n\n constructor(private sizes: Size[], private maxWidth: number, private minWidth: number, private spacing: number, private maxHeight = maxWidth) {\n this.count = sizes.length;\n this.ratios = Layouter.countRatios(sizes);\n this.proportions = Layouter.countProportions(this.ratios);\n this.averageRatio = accumulate(this.ratios, 1) / this.count; // warn\n this.maxSizeRatio = maxWidth / this.maxHeight;\n }\n\n public layout(): GroupMediaLayout[] {\n if(!this.count) return [];\n //else if(this.count === 1) return this.layoutOne();\n\n if(this.count >= 5 || this.ratios.find(r => r > 2)) {\n return new ComplexLayouter(this.ratios, this.averageRatio, this.maxWidth, this.minWidth, this.spacing).layout();\n }\n\n if(this.count === 2) return this.layoutTwo();\n else if(this.count === 3) return this.layoutThree();\n return this.layoutFour();\n }\n\n private layoutTwo(): ReturnType<Layouter['layout']> {\n if((this.proportions === \"ww\")\n && (this.averageRatio > 1.4 * this.maxSizeRatio)\n && (this.ratios[1] - this.ratios[0] < 0.2)) {\n return this.layoutTwoTopBottom();\n } else if(this.proportions === \"ww\" || this.proportions === \"qq\") {\n return this.layoutTwoLeftRightEqual();\n }\n return this.layoutTwoLeftRight();\n }\n\n private layoutThree(): ReturnType<Layouter['layout']> {\n //console.log('layoutThree:', this);\n if(this.proportions[0] === 'n') {\n return this.layoutThreeLeftAndOther();\n }\n return this.layoutThreeTopAndOther();\n }\n\n private layoutFour(): ReturnType<Layouter['layout']> {\n if(this.proportions[0] === 'w') {\n return this.layoutFourTopAndOther();\n }\n return this.layoutFourLeftAndOther();\n }\n\n private layoutTwoTopBottom(): ReturnType<Layouter['layout']> {\n const width = this.maxWidth;\n const height = Math.round(Math.min(\n width / this.ratios[0],\n Math.min(\n width / this.ratios[1],\n (this.maxHeight - this.spacing) / 2)));\n \n return [\n {\n geometry: {x: 0, y: 0, width, height},\n sides: RectPart.Left | RectPart.Top | RectPart.Right\n },\n {\n geometry: {x: 0, y: height + this.spacing, width, height},\n sides: RectPart.Left | RectPart.Bottom | RectPart.Right\n },\n ];\n }\n\n private layoutTwoLeftRightEqual(): ReturnType<Layouter['layout']> {\n const width = (this.maxWidth - this.spacing) / 2;\n const height = Math.round(Math.min(\n width / this.ratios[0],\n Math.min(width / this.ratios[1], this.maxHeight * 1)));\n \n return [\n {\n geometry: {x: 0, y: 0, width, height},\n sides: RectPart.Top | RectPart.Left | RectPart.Bottom\n },\n {\n geometry: {x: width + this.spacing, y: 0, width, height},\n sides: RectPart.Top | RectPart.Right | RectPart.Bottom\n },\n ];\n }\n\n private layoutTwoLeftRight(): ReturnType<Layouter['layout']> {\n const minimalWidth = Math.round(this.minWidth * 1.5);\n const secondWidth = Math.min(\n Math.round(Math.max(\n 0.4 * (this.maxWidth - this.spacing),\n (this.maxWidth - this.spacing) / this.ratios[0]\n / (1 / this.ratios[0] + 1 / this.ratios[1]))),\n this.maxWidth - this.spacing - minimalWidth);\n const firstWidth = this.maxWidth\n - secondWidth\n - this.spacing;\n const height = Math.min(\n this.maxHeight,\n Math.round(Math.min(\n firstWidth / this.ratios[0],\n secondWidth / this.ratios[1])));\n \n return [\n {\n geometry: {x: 0, y: 0, width: firstWidth, height},\n sides: RectPart.Top | RectPart.Left | RectPart.Bottom\n },\n {\n geometry: {x: firstWidth + this.spacing, y: 0, width: secondWidth, height},\n sides: RectPart.Top | RectPart.Right | RectPart.Bottom\n },\n ];\n }\n\n private layoutThreeLeftAndOther(): ReturnType<Layouter['layout']> {\n const firstHeight = this.maxHeight;\n const thirdHeight = Math.round(Math.min(\n (this.maxHeight - this.spacing) / 2.,\n (this.ratios[1] * (this.maxWidth - this.spacing)\n / (this.ratios[2] + this.ratios[1]))));\n const secondHeight = firstHeight\n - thirdHeight\n - this.spacing;\n const rightWidth = Math.max(\n this.minWidth,\n Math.round(Math.min(\n (this.maxWidth - this.spacing) / 2.,\n Math.min(\n thirdHeight * this.ratios[2],\n secondHeight * this.ratios[1]))));\n const leftWidth = Math.min(\n Math.round(firstHeight * this.ratios[0]),\n this.maxWidth - this.spacing - rightWidth);\n\n return [\n {\n geometry: {x: 0, y: 0, width: leftWidth, height: firstHeight},\n sides: RectPart.Top | RectPart.Left | RectPart.Bottom\n },\n {\n geometry: {x: leftWidth + this.spacing, y: 0, width: rightWidth, height: secondHeight},\n sides: RectPart.Top | RectPart.Right\n },\n {\n geometry: {x: leftWidth + this.spacing, y: secondHeight + this.spacing, width: rightWidth, height: thirdHeight},\n sides: RectPart.Bottom | RectPart.Right\n },\n ];\n }\n \n private layoutThreeTopAndOther(): ReturnType<Layouter['layout']> {\n const firstWidth = this.maxWidth;\n const firstHeight = Math.round(Math.min(\n firstWidth / this.ratios[0],\n (this.maxHeight - this.spacing) * 0.66));\n const secondWidth = (this.maxWidth - this.spacing) / 2;\n const secondHeight = Math.min(\n this.maxHeight - firstHeight - this.spacing,\n Math.round(Math.min(\n secondWidth / this.ratios[1],\n secondWidth / this.ratios[2])));\n const thirdWidth = firstWidth - secondWidth - this.spacing;\n \n return [\n {\n geometry: {x: 0, y: 0, width: firstWidth, height: firstHeight},\n sides: RectPart.Left | RectPart.Top | RectPart.Right\n },\n {\n geometry: {x: 0, y: firstHeight + this.spacing, width: secondWidth, height: secondHeight},\n sides: RectPart.Bottom | RectPart.Left\n },\n {\n geometry: {x: secondWidth + this.spacing, y: firstHeight + this.spacing, width: thirdWidth, height: secondHeight},\n sides: RectPart.Bottom | RectPart.Right\n },\n ];\n }\n\n private layoutFourTopAndOther(): ReturnType<Layouter['layout']> {\n const w = this.maxWidth;\n const h0 = Math.round(Math.min(\n w / this.ratios[0],\n (this.maxHeight - this.spacing) * 0.66));\n const h = Math.round(\n (this.maxWidth - 2 * this.spacing)\n / (this.ratios[1] + this.ratios[2] + this.ratios[3]));\n const w0 = Math.max(\n this.minWidth,\n Math.round(Math.min(\n (this.maxWidth - 2 * this.spacing) * 0.4,\n h * this.ratios[1])));\n const w2 = Math.round(Math.max(\n Math.max(\n this.minWidth * 1.,\n (this.maxWidth - 2 * this.spacing) * 0.33),\n h * this.ratios[3]));\n const w1 = w - w0 - w2 - 2 * this.spacing;\n const h1 = Math.min(\n this.maxHeight - h0 - this.spacing,\n h);\n \n return [\n {\n geometry: {x: 0, y: 0, width: w, height: h0},\n sides: RectPart.Left | RectPart.Top | RectPart.Right\n },\n {\n geometry: {x: 0, y: h0 + this.spacing, width: w0, height: h1},\n sides: RectPart.Bottom | RectPart.Left\n },\n {\n geometry: {x: w0 + this.spacing, y: h0 + this.spacing, width: w1, height: h1},\n sides: RectPart.Bottom,\n },\n {\n geometry: {x: w0 + this.spacing + w1 + this.spacing, y: h0 + this.spacing, width: w2, height: h1},\n sides: RectPart.Right | RectPart.Bottom\n },\n ];\n }\n\n private layoutFourLeftAndOther(): ReturnType<Layouter['layout']> {\n const h = this.maxHeight;\n const w0 = Math.round(Math.min(\n h * this.ratios[0],\n (this.maxWidth - this.spacing) * 0.6));\n \n const w = Math.round(\n (this.maxHeight - 2 * this.spacing)\n / (1. / this.ratios[1] + 1. / this.ratios[2] + 1. / this.ratios[3])\n );\n const h0 = Math.round(w / this.ratios[1]);\n const h1 = Math.round(w / this.ratios[2]);\n const h2 = h - h0 - h1 - 2 * this.spacing;\n const w1 = Math.max(\n this.minWidth,\n Math.min(this.maxWidth - w0 - this.spacing, w));\n \n return [\n {\n geometry: {x: 0, y: 0, width: w0, height: h},\n sides: RectPart.Top | RectPart.Left | RectPart.Bottom\n },\n {\n geometry: {x: w0 + this.spacing, y: 0, width: w1, height: h0},\n sides: RectPart.Top | RectPart.Right\n },\n {\n geometry: {x: w0 + this.spacing, y: h0 + this.spacing, width: w1, height: h1},\n sides: RectPart.Right\n },\n {\n geometry: {x: w0 + this.spacing, y: h0 + h1 + 2 * this.spacing, width: w1, height: h2},\n sides: RectPart.Bottom | RectPart.Right\n },\n ];\n }\n\n private static countRatios(sizes: Size[]) {\n return sizes.map(size => size.w / size.h);\n }\n\n private static countProportions(ratios: number[]) {\n return ratios.map(ratio => (ratio > 1.2) ? 'w' : (ratio < 0.8) ? 'n' : 'q').join('');\n }\n}\n\nclass ComplexLayouter {\n private ratios: number[];\n private count: number;\n\n constructor(ratios: number[], private averageRatio: number, private maxWidth: number, private minWidth: number, private spacing: number, private maxHeight = maxWidth * 4 / 3) {\n this.ratios = ComplexLayouter.cropRatios(ratios, averageRatio);\n this.count = ratios.length;\n }\n\n private static cropRatios(ratios: number[], averageRatio: number) {\n const kMaxRatio = 2.75;\n const kMinRatio = 0.6667;\n return ratios.map(ratio => {\n return averageRatio > 1.1\n\t\t\t ? clamp(ratio, 1., kMaxRatio)\n\t\t\t : clamp(ratio, kMinRatio, 1.);\n });\n }\n\n public layout(): GroupMediaLayout[] {\n let result = new Array<GroupMediaLayout>(this.count);\n\n let attempts: Attempt[] = [];\n const multiHeight = (offset: number, count: number) => {\n const ratios = this.ratios.slice(offset, offset + count); // warn\n const sum = accumulate(ratios, 0);\n return (this.maxWidth - (count - 1) * this.spacing) / sum;\n };\n const pushAttempt = (lineCounts: number[]) => {\n let heights: number[] = [];\n let offset = 0;\n for(let count of lineCounts) {\n heights.push(multiHeight(offset, count));\n offset += count;\n }\n attempts.push({lineCounts, heights}); // warn\n };\n\n for(let first = 1; first !== this.count; ++first) {\n const second = this.count - first;\n if(first > 3 || second > 3) {\n continue;\n }\n pushAttempt([first, second]);\n }\n for(let first = 1; first !== this.count - 1; ++first) {\n for(let second = 1; second !== this.count - first; ++second) {\n const third = this.count - first - second;\n if((first > 3)\n || (second > ((this.averageRatio < 0.85) ? 4 : 3))\n || (third > 3)) {\n continue;\n }\n pushAttempt([first, second, third]);\n }\n }\n for(let first = 1; first !== this.count - 1; ++first) {\n for(let second = 1; second !== this.count - first; ++second) {\n for(let third = 1; third !== this.count - first - second; ++third) {\n const fourth = this.count - first - second - third;\n if(first > 3 || second > 3 || third > 3 || fourth > 3) {\n continue;\n }\n pushAttempt([first, second, third, fourth]);\n }\n }\n }\n\n let optimalAttempt: Attempt = null;\n let optimalDiff = 0;\n for(const attempt of attempts) {\n const {heights, lineCounts: counts} = attempt;\n const lineCount = counts.length;\n const totalHeight = accumulate(heights, 0) \n + this.spacing * (lineCount - 1);\n const minLineHeight = Math.min(...heights);\n const maxLineHeight = Math.max(...heights);\n const bad1 = (minLineHeight < this.minWidth) ? 1.5 : 1;\n const bad2 = (() => {\n for(let line = 1; line !== lineCount; ++line) {\n if(counts[line - 1] > counts[line]) {\n return 1.5;\n }\n }\n return 1.;\n })();\n const diff = Math.abs(totalHeight - this.maxHeight) * bad1 * bad2;\n if(!optimalAttempt || diff < optimalDiff) {\n optimalAttempt = attempt;\n optimalDiff = diff;\n }\n }\n\n const optimalCounts = optimalAttempt.lineCounts;\n\t const optimalHeights = optimalAttempt.heights;\n const rowCount = optimalCounts.length;\n \n let index = 0;\n let y = 0;\n for(let row = 0; row !== rowCount; ++row) {\n const colCount = optimalCounts[row];\n const lineHeight = optimalHeights[row];\n const height = Math.round(lineHeight);\n\n let x = 0;\n for(let col = 0; col !== colCount; ++col) {\n const sides = RectPart.None\n | (row === 0 ? RectPart.Top : RectPart.None)\n | (row === rowCount - 1 ? RectPart.Bottom : RectPart.None)\n | (col === 0 ? RectPart.Left : RectPart.None)\n | (col === colCount - 1 ? RectPart.Right : RectPart.None);\n\n const ratio = this.ratios[index];\n const width = (col === colCount - 1)\n ? (this.maxWidth - x)\n : Math.round(ratio * lineHeight);\n result[index] = {\n geometry: {x, y, width, height},\n sides\n };\n\n x += width + this.spacing;\n ++index;\n }\n y += height + this.spacing;\n }\n\n return result;\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { InputFile } from \"../layer\";\nimport AvatarEdit from \"./avatarEdit\";\nimport AvatarElement from \"./avatar\";\nimport InputField from \"./inputField\";\nimport ListenerSetter from \"../helpers/listenerSetter\";\nimport Button from \"./button\";\nimport { safeAssign } from \"../helpers/object\";\n\nexport default class EditPeer {\n public nextBtn: HTMLButtonElement;\n\n public uploadAvatar: () => Promise<InputFile>;\n public avatarEdit: AvatarEdit;\n public avatarElem: AvatarElement;\n\n private inputFields: InputField[];\n private listenerSetter: ListenerSetter;\n\n private peerId: number;\n\n constructor(options: {\n peerId: number,\n inputFields: EditPeer['inputFields'],\n listenerSetter: ListenerSetter,\n doNotEditAvatar?: boolean,\n }) {\n safeAssign(this, options);\n\n this.nextBtn = Button('btn-circle btn-corner tgico-check');\n\n this.avatarElem = document.createElement('avatar-element') as AvatarElement;\n this.avatarElem.classList.add('avatar-placeholder', 'avatar-120');\n this.avatarElem.setAttribute('peer', '' + this.peerId);\n\n if(!options.doNotEditAvatar) {\n this.avatarEdit = new AvatarEdit((_upload) => {\n this.uploadAvatar = _upload;\n this.handleChange();\n this.avatarElem.remove();\n });\n\n this.avatarEdit.container.append(this.avatarElem);\n }\n\n this.inputFields.forEach(inputField => {\n this.listenerSetter.add(inputField.input, 'input', this.handleChange);\n });\n }\n\n public isChanged = () => {\n return !!this.uploadAvatar || !!this.inputFields.find(inputField => inputField.isValid());\n };\n\n public handleChange = () => {\n this.nextBtn.classList.toggle('is-visible', this.isChanged());\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport CheckboxField from \"./checkboxField\";\nimport RadioField from \"./radioField\";\nimport { ripple } from \"./ripple\";\nimport { SliderSuperTab } from \"./slider\";\nimport RadioForm from \"./radioForm\";\nimport { i18n, LangPackKey } from \"../lib/langPack\";\nimport { replaceContent } from \"../helpers/dom\";\n\nexport default class Row {\n public container: HTMLElement;\n public title: HTMLDivElement;\n public subtitle: HTMLElement;\n\n public checkboxField: CheckboxField;\n public radioField: RadioField;\n\n public freezed = false;\n\n constructor(options: Partial<{\n icon: string,\n subtitle: string,\n subtitleLangKey: LangPackKey\n radioField: Row['radioField'],\n checkboxField: Row['checkboxField'],\n noCheckboxSubtitle: boolean,\n title: string,\n titleLangKey: LangPackKey,\n titleRight: string | HTMLElement,\n clickable: boolean | ((e: Event) => void),\n navigationTab: SliderSuperTab\n }> = {}) {\n this.container = document.createElement(options.radioField || options.checkboxField ? 'label' : 'div');\n this.container.classList.add('row');\n\n this.subtitle = document.createElement('div');\n this.subtitle.classList.add('row-subtitle');\n if(options.subtitle) {\n this.subtitle.innerHTML = options.subtitle;\n } else if(options.subtitleLangKey) {\n this.subtitle.append(i18n(options.subtitleLangKey));\n }\n this.container.append(this.subtitle);\n\n let havePadding = false;\n if(options.radioField || options.checkboxField) {\n havePadding = true;\n if(options.radioField) {\n this.radioField = options.radioField;\n this.container.append(this.radioField.label);\n }\n\n if(options.checkboxField) {\n this.checkboxField = options.checkboxField;\n \n const isToggle = options.checkboxField.label.classList.contains('checkbox-field-toggle');\n if(isToggle) {\n this.container.classList.add('row-with-toggle');\n options.titleRight = this.checkboxField.label;\n } else {\n this.container.append(this.checkboxField.label);\n }\n\n if(!options.noCheckboxSubtitle && !isToggle) {\n this.checkboxField.input.addEventListener('change', () => {\n replaceContent(this.subtitle, i18n(this.checkboxField.input.checked ? 'Checkbox.Enabled' : 'Checkbox.Disabled'));\n });\n }\n }\n\n const i = options.radioField || options.checkboxField;\n i.label.classList.add('disable-hover');\n } \n \n if(options.title || options.titleLangKey) {\n let c: HTMLElement;\n if(options.titleRight) {\n c = document.createElement('div');\n c.classList.add('row-title-row');\n this.container.append(c);\n } else {\n c = this.container;\n }\n\n this.title = document.createElement('div');\n this.title.classList.add('row-title');\n if(options.title) {\n this.title.innerHTML = options.title;\n } else {\n this.title.append(i18n(options.titleLangKey));\n }\n c.append(this.title);\n\n if(options.titleRight) {\n const titleRight = document.createElement('div');\n titleRight.classList.add('row-title', 'row-title-right');\n\n if(typeof(options.titleRight) === 'string') {\n titleRight.innerHTML = options.titleRight;\n } else {\n titleRight.append(options.titleRight);\n }\n\n c.append(titleRight);\n }\n }\n\n if(options.icon) {\n havePadding = true;\n this.title.classList.add('tgico', 'tgico-' + options.icon);\n this.container.classList.add('row-with-icon');\n }\n\n if(havePadding) {\n this.container.classList.add('row-with-padding');\n }\n\n if(options.navigationTab) {\n options.clickable = () => options.navigationTab.open();\n }\n\n if(options.clickable || options.radioField || options.checkboxField) {\n if(typeof(options.clickable) === 'function') {\n this.container.addEventListener('click', (e) => {\n if(this.freezed) return;\n (options.clickable as any)(e);\n });\n }\n\n this.container.classList.add('row-clickable', 'hover-effect');\n ripple(this.container, undefined, undefined, true);\n\n /* if(options.radioField || options.checkboxField) {\n this.container.prepend(this.container.lastElementChild);\n } */\n }\n }\n\n\n}\n\nexport const RadioFormFromRows = (rows: Row[], onChange: (value: string) => void) => {\n return RadioForm(rows.map(r => ({container: r.container, input: r.radioField.input})), onChange);\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport default function RadioForm(radios: {container: HTMLElement, input: HTMLInputElement}[], onChange: (value: string) => void) {\n const form = document.createElement('form');\n\n radios.forEach(r => {\n const {container, input} = r;\n form.append(container);\n input.addEventListener('change', () => {\n if(input.checked) {\n onChange(input.value);\n }\n });\n });\n\n return form;\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\n// https://stackoverflow.com/a/30810322\nfunction fallbackCopyTextToClipboard(text: string) {\n var textArea = document.createElement(\"textarea\");\n textArea.value = text;\n \n // Avoid scrolling to bottom\n textArea.style.top = \"0\";\n textArea.style.left = \"0\";\n textArea.style.position = \"fixed\";\n\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n\n try {\n document.execCommand('copy');\n //const successful = document.execCommand('copy');\n //const msg = successful ? 'successful' : 'unsuccessful';\n //console.log('Fallback: Copying text command was ' + msg);\n } catch(err) {\n //console.error('Fallback: Oops, unable to copy', err);\n }\n\n document.body.removeChild(textArea);\n}\n\nexport function copyTextToClipboard(text: string) {\n if(!navigator.clipboard) {\n fallbackCopyTextToClipboard(text);\n return;\n }\n \n navigator.clipboard.writeText(text);/* .then(function() {\n console.log('Async: Copying to clipboard was successful!');\n }, function(err) {\n console.error('Async: Could not copy text: ', err);\n }); */\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appStateManager from \"../lib/appManagers/appStateManager\";\nimport { getDeepProperty } from \"../helpers/object\";\nimport { LangPackKey, _i18n } from \"../lib/langPack\";\n\nexport default class RadioField {\n public input: HTMLInputElement;\n public label: HTMLLabelElement;\n public main: HTMLElement;\n\n constructor(options: {\n text?: string, \n langKey?: LangPackKey,\n name: string, \n value?: string, \n stateKey?: string\n }) {\n const label = this.label = document.createElement('label');\n label.classList.add('radio-field');\n \n const input = this.input = document.createElement('input');\n input.type = 'radio';\n /* input.id = */input.name = 'input-radio-' + options.name;\n \n if(options.value) {\n input.value = options.value;\n \n if(options.stateKey) {\n appStateManager.getState().then(state => {\n input.checked = getDeepProperty(state, options.stateKey) === options.value;\n });\n \n input.addEventListener('change', () => {\n appStateManager.setByKey(options.stateKey, options.value);\n });\n }\n }\n \n const main = this.main = document.createElement('div');\n main.classList.add('radio-field-main');\n \n if(options.text) {\n main.innerHTML = options.text;\n /* const caption = document.createElement('div');\n caption.classList.add('radio-field-main-caption');\n caption.innerHTML = text;\n \n if(subtitle) {\n label.classList.add('radio-field-with-subtitle');\n caption.insertAdjacentHTML('beforeend', `<div class=\"radio-field-main-subtitle\">${subtitle}</div>`);\n }\n \n main.append(caption); */\n } else if(options.langKey) {\n _i18n(main, options.langKey);\n }\n \n label.append(input, main);\n }\n\n get checked() {\n return this.input.checked;\n }\n\n set checked(checked: boolean) {\n this.setValueSilently(checked);\n\n const event = new Event('change', {bubbles: true, cancelable: true});\n this.input.dispatchEvent(event);\n }\n\n public setValueSilently(checked: boolean) {\n this.input.checked = checked;\n }\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nconst toastEl = document.createElement('div');\ntoastEl.classList.add('toast');\nexport function toast(html: string) {\n toastEl.innerHTML = html;\n document.body.append(toastEl);\n\n if(toastEl.dataset.timeout) clearTimeout(+toastEl.dataset.timeout);\n toastEl.dataset.timeout = '' + setTimeout(() => {\n toastEl.remove();\n delete toastEl.dataset.timeout;\n }, 3000);\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport ListenerSetter from \"../helpers/listenerSetter\";\nimport { debounce } from \"../helpers/schedulers\";\nimport appChatsManager from \"../lib/appManagers/appChatsManager\";\nimport { LangPackKey } from \"../lib/langPack\";\nimport apiManager from \"../lib/mtproto/mtprotoworker\";\nimport RichTextProcessor from \"../lib/richtextprocessor\";\nimport InputField, { InputFieldOptions, InputState } from \"./inputField\";\n\nexport class UsernameInputField extends InputField {\n private checkUsernamePromise: Promise<any>;\n private checkUsernameDebounced: (username: string) => void;\n public options: InputFieldOptions & {\n peerId: number,\n listenerSetter: ListenerSetter,\n onChange?: () => void,\n invalidText: LangPackKey,\n takenText: LangPackKey,\n availableText: LangPackKey,\n head?: string\n };\n\n constructor(options: UsernameInputField['options']) {\n super(options);\n\n this.checkUsernameDebounced = debounce(this.checkUsername.bind(this), 150, false, true);\n\n options.listenerSetter.add(this.input, 'input', () => {\n const value = this.getValue();\n\n //console.log('userNameInput:', value);\n if(value === this.originalValue || !value.length) {\n this.setState(InputState.Neutral, this.options.label);\n this.options.onChange && this.options.onChange();\n return;\n } else if(!RichTextProcessor.isUsernameValid(value)) { // does not check the last underscore\n this.setError(this.options.invalidText);\n } else {\n this.setState(InputState.Neutral);\n }\n\n if(this.input.classList.contains('error')) {\n this.options.onChange && this.options.onChange();\n return;\n }\n\n this.checkUsernameDebounced(value);\n });\n }\n\n public getValue() {\n let value = this.value;\n if(this.options.head) {\n value = value.slice(this.options.head.length);\n this.setValueSilently(this.options.head + value);\n }\n\n return value;\n }\n\n private checkUsername(username: string) {\n if(this.checkUsernamePromise) return;\n\n if(this.options.peerId) {\n this.checkUsernamePromise = apiManager.invokeApi('channels.checkUsername', {\n channel: appChatsManager.getChannelInput(-this.options.peerId),\n username\n });\n } else {\n this.checkUsernamePromise = apiManager.invokeApi('account.checkUsername', {username});\n }\n\n this.checkUsernamePromise.then(available => {\n if(this.getValue() !== username) return;\n\n if(available) {\n this.setState(InputState.Valid, this.options.availableText);\n } else {\n this.setError(this.options.takenText);\n }\n }, (err) => {\n if(this.getValue() !== username) return;\n\n switch(err.type) {\n case 'USERNAME_INVALID': {\n this.setError(this.options.invalidText);\n break;\n }\n }\n }).then(() => {\n this.checkUsernamePromise = undefined;\n this.options.onChange && this.options.onChange();\n\n const value = this.getValue();\n if(value !== username && this.isValid() && RichTextProcessor.isUsernameValid(value)) {\n this.checkUsername(value);\n }\n });\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport AvatarElement from \"../avatar\";\nimport PopupElement, { addCancelButton, PopupButton, PopupOptions } from \".\";\nimport { i18n, LangPackKey } from \"../../lib/langPack\";\nimport CheckboxField, { CheckboxFieldOptions } from \"../checkboxField\";\n\nexport type PopupPeerButtonCallbackCheckboxes = Partial<{[text in LangPackKey]: boolean}>;\nexport type PopupPeerButtonCallback = (checkboxes?: PopupPeerButtonCallbackCheckboxes) => void;\n\nexport type PopupPeerOptions = PopupOptions & Partial<{\n peerId: number,\n title: string,\n titleLangKey?: LangPackKey,\n titleLangArgs?: any[],\n description: string,\n descriptionLangKey?: LangPackKey,\n descriptionLangArgs?: any[],\n buttons: Array<Omit<PopupButton, 'callback'> & Partial<{callback: PopupPeerButtonCallback}>>,\n checkboxes: Array<CheckboxFieldOptions & {checkboxField?: CheckboxField}>\n}>;\nexport default class PopupPeer extends PopupElement {\n constructor(private className: string, options: PopupPeerOptions = {}) {\n super('popup-peer' + (className ? ' ' + className : ''), addCancelButton(options.buttons), {overlayClosable: true, ...options});\n\n if(options.peerId) {\n let avatarEl = new AvatarElement();\n avatarEl.setAttribute('dialog', '1');\n avatarEl.setAttribute('peer', '' + options.peerId);\n avatarEl.classList.add('avatar-32');\n this.header.prepend(avatarEl);\n }\n\n if(options.descriptionLangKey) this.title.append(i18n(options.titleLangKey, options.titleLangArgs));\n else this.title.innerText = options.title || '';\n\n let p = document.createElement('p');\n p.classList.add('popup-description');\n if(options.descriptionLangKey) p.append(i18n(options.descriptionLangKey, options.descriptionLangArgs));\n else p.innerHTML = options.description;\n\n const fragment = document.createDocumentFragment();\n fragment.append(p);\n\n if(options.checkboxes) {\n this.container.classList.add('have-checkbox');\n \n options.checkboxes.forEach(o => {\n o.withRipple = true;\n const checkboxField = new CheckboxField(o);\n o.checkboxField = checkboxField;\n fragment.append(checkboxField.label);\n });\n\n options.buttons.forEach(button => {\n if(button.callback) {\n const original = button.callback;\n button.callback = () => {\n const c: PopupPeerButtonCallbackCheckboxes = {};\n options.checkboxes.forEach(o => {\n c[o.text] = o.checkboxField.checked;\n });\n original(c);\n };\n }\n });\n }\n\n this.container.insertBefore(fragment, this.header.nextElementSibling);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { copyTextToClipboard } from \"../../../helpers/clipboard\";\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport { randomLong } from \"../../../helpers/random\";\nimport { Chat, ChatFull, ExportedChatInvite } from \"../../../layer\";\nimport appChatsManager from \"../../../lib/appManagers/appChatsManager\";\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport Button from \"../../button\";\nimport { setButtonLoader } from \"../../misc\";\nimport RadioField from \"../../radioField\";\nimport Row, { RadioFormFromRows } from \"../../row\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport { toast } from \"../../toast\";\nimport { UsernameInputField } from \"../../usernameInputField\";\nimport { SliderSuperTabEventable } from \"../../sliderTab\";\nimport I18n from \"../../../lib/langPack\";\nimport PopupPeer from \"../../popups/peer\";\n\nexport default class AppGroupTypeTab extends SliderSuperTabEventable {\n public peerId: number;\n public chatFull: ChatFull;\n\n protected init() {\n this.container.classList.add('edit-peer-container', 'group-type-container');\n this.setTitle('GroupType');\n\n const section = new SettingSection({\n name: 'GroupType'\n });\n\n const random = randomLong();\n const privateRow = new Row({\n radioField: new RadioField({\n langKey: 'MegaPrivate', \n name: random, \n value: 'private'\n }),\n subtitleLangKey: 'MegaPrivateInfo'\n });\n const publicRow = new Row({\n radioField: new RadioField({\n langKey: 'MegaPublic', \n name: random, \n value: 'public'\n }),\n subtitleLangKey: 'MegaPublicInfo'\n });\n const form = RadioFormFromRows([privateRow, publicRow], (value) => {\n const a = [privateSection, publicSection];\n if(value === 'public') a.reverse();\n\n a[0].container.classList.remove('hide');\n a[1].container.classList.add('hide');\n\n onChange();\n });\n\n const chat: Chat = appChatsManager.getChat(-this.peerId);\n\n section.content.append(form);\n\n const privateSection = new SettingSection({});\n\n //let revoked = false;\n const linkRow = new Row({\n title: (this.chatFull.exported_invite as ExportedChatInvite.chatInviteExported).link,\n subtitleLangKey: 'MegaPrivateLinkHelp',\n clickable: () => {\n copyTextToClipboard((this.chatFull.exported_invite as ExportedChatInvite.chatInviteExported).link);\n toast(I18n.format('LinkCopied', true));\n }\n });\n\n const btnRevoke = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'RevokeLink'});\n\n attachClickEvent(btnRevoke, () => {\n new PopupPeer('revoke-link', {\n buttons: [{\n langKey: 'RevokeButton',\n callback: () => {\n const toggle = toggleDisability([btnRevoke], true);\n \n appProfileManager.getChatInviteLink(-this.peerId, true).then(link => {\n toggle();\n linkRow.title.innerHTML = link;\n //revoked = true;\n //onChange();\n });\n }\n }],\n titleLangKey: 'RevokeLink',\n descriptionLangKey: 'RevokeAlert'\n }).show();\n }, {listenerSetter: this.listenerSetter});\n\n privateSection.content.append(linkRow.container, btnRevoke);\n\n const publicSection = new SettingSection({\n caption: 'Channel.UsernameAboutGroup',\n noDelimiter: true\n });\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const placeholder = 't.me/';\n\n const onChange = () => {\n const changed = (privateRow.radioField.checked && (originalValue !== placeholder/* || revoked */)) \n || (linkInputField.isValid() && linkInputField.input.classList.contains('valid'));\n applyBtn.classList.toggle('is-visible', changed);\n };\n\n const linkInputField = new UsernameInputField({\n label: 'SetUrlPlaceholder',\n name: 'group-public-link',\n plainText: true,\n listenerSetter: this.listenerSetter,\n availableText: 'Link.Available',\n invalidText: 'Link.Invalid',\n takenText: 'Link.Taken',\n onChange: onChange,\n peerId: this.peerId,\n head: placeholder\n });\n\n const originalValue = placeholder + ((chat as Chat.channel).username || '');\n\n inputWrapper.append(linkInputField.container)\n publicSection.content.append(inputWrapper);\n\n const applyBtn = Button('btn-circle btn-corner tgico-check is-visible');\n this.content.append(applyBtn);\n\n attachClickEvent(applyBtn, () => {\n /* const unsetLoader = */setButtonLoader(applyBtn);\n const username = publicRow.radioField.checked ? linkInputField.getValue() : '';\n appChatsManager.migrateChat(-this.peerId).then(channelId => {\n return appChatsManager.updateUsername(channelId, username);\n }).then(() => {\n //unsetLoader();\n this.close();\n });\n }, {listenerSetter: this.listenerSetter});\n\n (originalValue !== placeholder ? publicRow : privateRow).radioField.checked = true;\n linkInputField.setOriginalValue(originalValue);\n\n this.scrollable.append(section.container, privateSection.container, publicSection.container);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport Scrollable from \"../components/scrollable\";\nimport { safeAssign } from \"./object\";\n\nexport default class ScrollableLoader {\n public loading = false;\n private scrollable: Scrollable;\n private getPromise: () => Promise<any>;\n private promise: Promise<any>;\n private loaded = false;\n\n constructor(options: {\n scrollable: ScrollableLoader['scrollable'],\n getPromise: ScrollableLoader['getPromise']\n }) {\n safeAssign(this, options);\n\n options.scrollable.onScrolledBottom = () => {\n this.load();\n };\n }\n \n public load() {\n if(this.loaded) {\n return Promise.resolve();\n }\n \n if(this.loading) {\n return this.promise;\n }\n\n this.loading = true;\n this.promise = this.getPromise().then(done => {\n this.loading = false;\n this.promise = undefined;\n\n if(done) {\n this.loaded = true;\n this.scrollable.onScrolledBottom = null;\n } else {\n this.scrollable.checkForTriggers();\n }\n }, () => {\n this.promise = undefined;\n this.loading = false;\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appChatsManager, { ChatRights } from \"../lib/appManagers/appChatsManager\";\nimport appDialogsManager from \"../lib/appManagers/appDialogsManager\";\nimport appMessagesManager, { Dialog } from \"../lib/appManagers/appMessagesManager\";\nimport appPhotosManager from \"../lib/appManagers/appPhotosManager\";\nimport appUsersManager from \"../lib/appManagers/appUsersManager\";\nimport rootScope from \"../lib/rootScope\";\nimport { cancelEvent, replaceContent } from \"../helpers/dom\";\nimport Scrollable from \"./scrollable\";\nimport { FocusDirection } from \"../helpers/fastSmoothScroll\";\nimport CheckboxField from \"./checkboxField\";\nimport appProfileManager from \"../lib/appManagers/appProfileManager\";\nimport { safeAssign } from \"../helpers/object\";\nimport { i18n, LangPackKey, _i18n } from \"../lib/langPack\";\nimport findUpAttribute from \"../helpers/dom/findUpAttribute\";\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\nimport PeerTitle from \"./peerTitle\";\n\ntype PeerType = 'contacts' | 'dialogs' | 'channelParticipants';\n\n// TODO: правильная сортировка для addMembers, т.е. для peerType: 'contacts', потому что там идут сначала контакты - потом неконтакты, а должно всё сортироваться по имени\n\nlet loadedAllDialogs = false, loadAllDialogsPromise: Promise<any>;\nexport default class AppSelectPeers {\n public container = document.createElement('div');\n public list = appDialogsManager.createChatList(/* {\n handheldsSize: 66,\n avatarSize: 48\n } */);\n public chatsContainer = document.createElement('div');\n public scrollable: Scrollable;\n public selectedScrollable: Scrollable;\n \n public selectedContainer: HTMLElement;\n public input: HTMLInputElement;\n \n //public selected: {[peerId: number]: HTMLElement} = {};\n public selected = new Set<any>();\n\n public freezed = false;\n\n private folderId = 0;\n private offsetIndex = 0;\n private promise: Promise<any>;\n\n private query = '';\n private cachedContacts: number[];\n\n private loadedWhat: Partial<{[k in 'dialogs' | 'archived' | 'contacts' | 'channelParticipants']: true}> = {};\n\n private renderedPeerIds: Set<number> = new Set();\n\n private appendTo: HTMLElement;\n private onChange: (length: number) => void;\n private peerType: PeerType[] = ['dialogs'];\n private renderResultsFunc: (peerIds: number[]) => void;\n private chatRightsAction: ChatRights;\n private multiSelect = true;\n private rippleEnabled = true;\n private avatarSize = 48;\n\n private tempIds: {[k in keyof AppSelectPeers['loadedWhat']]: number} = {};\n private peerId = 0;\n\n private placeholder: LangPackKey;\n \n constructor(options: {\n appendTo: AppSelectPeers['appendTo'], \n onChange?: AppSelectPeers['onChange'], \n peerType?: AppSelectPeers['peerType'], \n peerId?: number,\n onFirstRender?: () => void, \n renderResultsFunc?: AppSelectPeers['renderResultsFunc'], \n chatRightsAction?: AppSelectPeers['chatRightsAction'], \n multiSelect?: AppSelectPeers['multiSelect'],\n rippleEnabled?: boolean,\n avatarSize?: AppSelectPeers['avatarSize'],\n placeholder?: LangPackKey\n }) {\n safeAssign(this, options);\n\n this.container.classList.add('selector');\n\n let needSwitchList = false;\n const f = (this.renderResultsFunc || this.renderResults).bind(this);\n this.renderResultsFunc = (peerIds: number[]) => {\n if(needSwitchList) {\n this.scrollable.splitUp.replaceWith(this.list);\n this.scrollable.setVirtualContainer(this.list);\n needSwitchList = false;\n }\n \n peerIds = peerIds.filter(peerId => {\n const notRendered = !this.renderedPeerIds.has(peerId);\n if(notRendered) this.renderedPeerIds.add(peerId);\n return notRendered;\n });\n\n return f(peerIds);\n };\n\n this.input = document.createElement('input');\n this.input.classList.add('selector-search-input');\n if(this.placeholder) {\n _i18n(this.input, this.placeholder, undefined, 'placeholder');\n } else {\n _i18n(this.input, 'SendMessageTo', undefined, 'placeholder');\n }\n\n this.input.type = 'text';\n\n if(this.multiSelect) {\n let topContainer = document.createElement('div');\n topContainer.classList.add('selector-search-container');\n \n this.selectedContainer = document.createElement('div');\n this.selectedContainer.classList.add('selector-search');\n \n this.selectedContainer.append(this.input);\n topContainer.append(this.selectedContainer);\n this.selectedScrollable = new Scrollable(topContainer);\n \n let delimiter = document.createElement('hr');\n\n this.selectedContainer.addEventListener('click', (e) => {\n if(this.freezed) return;\n let target = e.target as HTMLElement;\n target = findUpClassName(target, 'selector-user');\n \n if(!target) return;\n \n const peerId = target.dataset.key;\n const li = this.chatsContainer.querySelector('[data-peer-id=\"' + peerId + '\"]') as HTMLElement;\n if(!li) {\n this.remove(+peerId || peerId);\n } else {\n li.click();\n }\n });\n\n this.container.append(topContainer, delimiter);\n }\n\n this.chatsContainer.classList.add('chatlist-container');\n this.chatsContainer.append(this.list);\n this.scrollable = new Scrollable(this.chatsContainer);\n this.scrollable.setVirtualContainer(this.list);\n\n this.chatsContainer.addEventListener('click', (e) => {\n const target = findUpAttribute(e.target, 'data-peer-id') as HTMLElement;\n cancelEvent(e);\n\n if(!target) return;\n if(this.freezed) return;\n\n let key: any = target.dataset.peerId;\n key = +key || key;\n\n if(!this.multiSelect) {\n this.add(key);\n return;\n }\n\n //target.classList.toggle('active');\n if(this.selected.has(key)) {\n this.remove(key);\n } else {\n this.add(key);\n }\n\n const checkbox = target.querySelector('input') as HTMLInputElement;\n checkbox.checked = !checkbox.checked;\n });\n\n this.input.addEventListener('input', () => {\n const value = this.input.value;\n if(this.query !== value) {\n if(this.peerType.includes('contacts')) {\n this.cachedContacts = null;\n }\n \n //if(this.peerType.includes('dialogs')) {\n this.folderId = 0;\n this.offsetIndex = 0;\n //}\n\n for(let i in this.tempIds) {\n // @ts-ignore\n ++this.tempIds[i];\n }\n\n this.list = appDialogsManager.createChatList();\n\n this.promise = null;\n this.loadedWhat = {};\n this.query = value;\n this.renderedPeerIds.clear();\n needSwitchList = true;\n \n //console.log('selectPeers input:', this.query);\n this.getMoreResults();\n }\n });\n\n this.scrollable.onScrolledBottom = () => {\n this.getMoreResults();\n };\n\n this.container.append(this.chatsContainer);\n this.appendTo.append(this.container);\n\n // WARNING TIMEOUT\n setTimeout(() => {\n let getResultsPromise = this.getMoreResults() as Promise<any>;\n if(options.onFirstRender) {\n getResultsPromise.then(() => {\n options.onFirstRender();\n });\n }\n }, 0);\n }\n\n private renderSaved() {\n if(!this.offsetIndex && this.folderId === 0 && this.peerType.includes('dialogs') && (!this.query || appUsersManager.testSelfSearch(this.query))) {\n this.renderResultsFunc([rootScope.myId]);\n }\n }\n\n private getTempId(type: keyof AppSelectPeers['tempIds']) {\n if(this.tempIds[type] === undefined) {\n this.tempIds[type] = 0;\n }\n\n return ++this.tempIds[type];\n }\n\n private async getMoreDialogs(): Promise<any> {\n if(this.promise) return this.promise;\n\n if(this.loadedWhat.dialogs && this.loadedWhat.archived) {\n return;\n }\n \n // в десктопе - сначала без группы, потом архивные, потом контакты без сообщений\n const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;\n\n const tempId = this.getTempId('dialogs');\n this.promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderId);\n const value = await this.promise;\n this.promise = null;\n\n if(this.tempIds.dialogs !== tempId) {\n return;\n }\n\n let dialogs = value.dialogs as Dialog[];\n if(dialogs.length) {\n const newOffsetIndex = dialogs[dialogs.length - 1].index || 0;\n\n dialogs = dialogs.slice();\n dialogs.findAndSplice(d => d.peerId === rootScope.myId); // no my account\n\n if(this.chatRightsAction) {\n dialogs = dialogs.filter(d => {\n return (d.peerId > 0 && (this.chatRightsAction !== 'send_messages' || appUsersManager.canSendToUser(d.peerId))) || appChatsManager.hasRights(-d.peerId, this.chatRightsAction);\n });\n }\n\n this.renderSaved();\n\n this.offsetIndex = newOffsetIndex;\n\n this.renderResultsFunc(dialogs.map(dialog => dialog.peerId));\n } else {\n if(!this.loadedWhat.dialogs) {\n this.renderSaved();\n\n this.loadedWhat.dialogs = true;\n this.offsetIndex = 0;\n this.folderId = 1;\n\n return this.getMoreDialogs();\n } else {\n this.loadedWhat.archived = true;\n\n if(!this.loadedWhat.contacts && this.peerType.includes('contacts')) {\n return this.getMoreContacts();\n }\n }\n }\n }\n\n private async getMoreContacts() {\n if(this.promise) return this.promise;\n\n if(this.loadedWhat.contacts) {\n return;\n }\n\n if(!this.cachedContacts) {\n /* const promises: Promise<any>[] = [appUsersManager.getContacts(this.query)];\n if(!this.peerType.includes('dialogs')) {\n promises.push(appMessagesManager.getConversationsAll());\n }\n\n this.promise = Promise.all(promises);\n this.cachedContacts = (await this.promise)[0].slice(); */\n const tempId = this.getTempId('contacts');\n this.promise = appUsersManager.getContacts(this.query);\n this.cachedContacts = (await this.promise).slice();\n if(this.tempIds.contacts !== tempId) {\n return;\n }\n\n this.cachedContacts.findAndSplice(userId => userId === rootScope.myId); // no my account\n this.promise = null;\n }\n\n if(this.cachedContacts.length) {\n const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;\n const arr = this.cachedContacts.splice(0, pageCount);\n this.renderResultsFunc(arr);\n }\n \n if(!this.cachedContacts.length) {\n this.loadedWhat.contacts = true;\n\n // need to load non-contacts\n if(!this.peerType.includes('dialogs')) {\n return this.getMoreDialogs();\n }\n }\n }\n\n private async getMoreChannelParticipants() {\n if(this.promise) return this.promise;\n\n if(this.loadedWhat.channelParticipants) {\n return;\n }\n\n const pageCount = 50; // same as in group permissions to use cache\n\n const tempId = this.getTempId('channelParticipants');\n const promise = appProfileManager.getChannelParticipants(-this.peerId, {_: 'channelParticipantsSearch', q: this.query}, pageCount, this.list.childElementCount);\n const participants = await promise;\n if(this.tempIds.channelParticipants !== tempId) {\n return;\n }\n \n const userIds = participants.participants.map(participant => participant.user_id);\n userIds.findAndSplice(u => u === rootScope.myId);\n this.renderResultsFunc(userIds);\n\n if(this.list.childElementCount >= participants.count || participants.participants.length < pageCount) {\n this.loadedWhat.channelParticipants = true;\n }\n }\n\n checkForTriggers = () => {\n this.scrollable.checkForTriggers();\n };\n\n private getMoreResults() {\n const get = () => {\n const promises: Promise<any>[] = [];\n\n if(!loadedAllDialogs && (this.peerType.includes('dialogs') || this.peerType.includes('contacts'))) {\n if(!loadAllDialogsPromise) {\n loadAllDialogsPromise = appMessagesManager.getConversationsAll()\n .then(() => {\n loadedAllDialogs = true;\n }).finally(() => {\n loadAllDialogsPromise = null;\n });\n }\n\n promises.push(loadAllDialogsPromise);\n }\n \n if((this.peerType.includes('dialogs') || this.loadedWhat.contacts) && !this.loadedWhat.archived) { // to load non-contacts\n promises.push(this.getMoreDialogs());\n \n if(!this.loadedWhat.archived) {\n return promises;\n }\n }\n \n if(this.peerType.includes('contacts') && !this.loadedWhat.contacts) {\n promises.push(this.getMoreContacts());\n }\n\n if(this.peerType.includes('channelParticipants') && !this.loadedWhat.channelParticipants) {\n promises.push(this.getMoreChannelParticipants());\n }\n \n return promises;\n };\n \n const promises = get();\n const promise = Promise.all(promises);\n if(promises.length) {\n promise.then(this.checkForTriggers);\n }\n\n return promise;\n }\n\n private renderResults(peerIds: number[]) {\n //console.log('will renderResults:', peerIds);\n\n // оставим только неконтакты с диалогов\n if(!this.peerType.includes('dialogs') && this.loadedWhat.contacts) {\n peerIds = peerIds.filter(peerId => {\n return appUsersManager.isNonContactUser(peerId);\n });\n }\n\n peerIds.forEach(peerId => {\n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: this.scrollable,\n drawStatus: false,\n rippleEnabled: this.rippleEnabled,\n avatarSize: this.avatarSize\n });\n\n if(this.multiSelect) {\n const selected = this.selected.has(peerId);\n const checkboxField = new CheckboxField();\n\n if(selected) {\n //dom.listEl.classList.add('active');\n checkboxField.input.checked = true;\n }\n\n dom.containerEl.prepend(checkboxField.label);\n }\n\n let subtitleEl: HTMLElement;\n if(peerId < 0) {\n subtitleEl = appChatsManager.getChatMembersString(-peerId);\n } else if(peerId === rootScope.myId) {\n subtitleEl = i18n('Presence.YourChat');\n } else {\n subtitleEl = appUsersManager.getUserStatusString(peerId);\n }\n\n dom.lastMessageSpan.append(subtitleEl);\n });\n }\n\n public add(peerId: any, title?: string | HTMLElement, scroll = true) {\n //console.trace('add');\n this.selected.add(peerId);\n\n if(!this.multiSelect) {\n this.onChange(this.selected.size);\n return;\n }\n\n const div = document.createElement('div');\n div.classList.add('selector-user', 'scale-in');\n\n const avatarEl = document.createElement('avatar-element');\n avatarEl.classList.add('selector-user-avatar', 'tgico');\n avatarEl.setAttribute('dialog', '1');\n avatarEl.classList.add('avatar-32');\n\n div.dataset.key = '' + peerId;\n if(typeof(peerId) === 'number') {\n if(title === undefined) {\n title = new PeerTitle({peerId, onlyFirstName: true}).element;\n }\n\n avatarEl.setAttribute('peer', '' + peerId);\n }\n\n if(title) {\n if(typeof(title) === 'string') {\n div.innerHTML = title;\n } else {\n replaceContent(div, title);\n div.append(title);\n }\n }\n\n div.insertAdjacentElement('afterbegin', avatarEl);\n\n this.selectedContainer.insertBefore(div, this.input);\n //this.selectedScrollable.scrollTop = this.selectedScrollable.scrollHeight;\n this.onChange && this.onChange(this.selected.size);\n \n if(scroll) {\n this.selectedScrollable.scrollIntoViewNew(this.input, 'center');\n }\n \n return div;\n }\n\n public remove(key: any) {\n if(!this.multiSelect) return;\n //const div = this.selected[peerId];\n const div = this.selectedContainer.querySelector(`[data-key=\"${key}\"]`) as HTMLElement;\n div.classList.remove('scale-in');\n void div.offsetWidth;\n div.classList.add('scale-out');\n\n const onAnimationEnd = () => {\n this.selected.delete(key);\n div.remove();\n this.onChange && this.onChange(this.selected.size);\n };\n\n if(rootScope.settings.animationsEnabled) {\n div.addEventListener('animationend', onAnimationEnd, {once: true});\n } else {\n onAnimationEnd();\n }\n }\n\n public getSelected() {\n return [...this.selected];\n }\n\n public addInitial(values: any[]) {\n values.forEach(value => {\n this.add(value, undefined, false);\n });\n\n window.requestAnimationFrame(() => { // ! not the best place for this raf though it works\n this.selectedScrollable.scrollIntoViewNew(this.input, 'center', undefined, undefined, FocusDirection.Static);\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport default function findUpAttribute(el: any, attribute: string): HTMLElement {\n return el.closest(`[${attribute}]`);\n /* if(el.getAttribute(attribute) !== null) return el; // 03.02.2020\n\n while(el.parentElement) {\n el = el.parentElement;\n if(el.getAttribute(attribute) !== null) \n return el;\n }\n return null; */\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport AppSelectPeers from \"../appSelectPeers\";\nimport PopupElement from \".\";\nimport { LangPackKey, _i18n } from \"../../lib/langPack\";\n\nexport default class PopupPickUser extends PopupElement {\n protected selector: AppSelectPeers;\n \n constructor(options: {\n peerTypes: AppSelectPeers['peerType'], \n onSelect?: (peerId: number) => Promise<void> | void, \n onClose?: () => void,\n placeholder: LangPackKey,\n chatRightsAction?: AppSelectPeers['chatRightsAction'],\n peerId?: number,\n }) {\n super('popup-forward', null, {closable: true, overlayClosable: true, body: true});\n\n if(options.onClose) this.onClose = options.onClose;\n\n this.selector = new AppSelectPeers({\n appendTo: this.body, \n onChange: async() => {\n const peerId = this.selector.getSelected()[0];\n \n this.selector = null;\n \n if(options.onSelect) {\n const res = options.onSelect(peerId);\n if(res instanceof Promise) {\n await res;\n }\n }\n \n this.hide();\n }, \n peerType: options.peerTypes, \n onFirstRender: () => {\n this.show();\n this.selector.checkForTriggers(); // ! due to zero height before mounting\n\n if(!isTouchSupported) {\n this.selector.input.focus();\n }\n }, \n chatRightsAction: options.chatRightsAction, \n multiSelect: false,\n rippleEnabled: false,\n avatarSize: 46,\n peerId: options.peerId,\n placeholder: options.placeholder\n });\n\n //this.scrollable = new Scrollable(this.body);\n\n this.title.append(this.selector.input);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport { deepEqual } from \"../../../helpers/object\";\nimport { ChannelParticipant } from \"../../../layer\";\nimport appChatsManager from \"../../../lib/appManagers/appChatsManager\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appPeersManager from \"../../../lib/appManagers/appPeersManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport Button from \"../../button\";\nimport { addCancelButton } from \"../../popups\";\nimport PopupPeer from \"../../popups/peer\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport { SliderSuperTabEventable } from \"../../sliderTab\";\nimport { ChatPermissions } from \"./groupPermissions\";\n\nexport default class AppUserPermissionsTab extends SliderSuperTabEventable {\n public participant: ChannelParticipant;\n public chatId: number;\n public userId: number;\n\n protected init() {\n this.container.classList.add('edit-peer-container', 'user-permissions-container');\n this.setTitle('UserRestrictions');\n\n let destroyListener: () => void;\n\n {\n const section = new SettingSection({\n name: 'UserRestrictionsCanDo',\n });\n \n const div = document.createElement('div');\n div.classList.add('chatlist-container');\n section.content.insertBefore(div, section.title);\n\n const list = appDialogsManager.createChatList();\n div.append(list);\n\n const {dom} = appDialogsManager.addDialogNew({\n dialog: this.userId,\n container: list,\n drawStatus: false,\n rippleEnabled: true,\n avatarSize: 48\n });\n\n dom.lastMessageSpan.append(appUsersManager.getUserStatusString(this.userId));\n\n const p = new ChatPermissions({\n chatId: this.chatId,\n listenerSetter: this.listenerSetter,\n appendTo: section.content,\n participant: this.participant._ === 'channelParticipantBanned' ? this.participant : undefined\n });\n\n destroyListener = () => {\n //appChatsManager.editChatDefaultBannedRights(this.chatId, p.takeOut());\n const rights = p.takeOut();\n if(this.participant._ === 'channelParticipantBanned' && deepEqual(this.participant.banned_rights.pFlags, rights.pFlags)) {\n return;\n }\n\n appChatsManager.editBanned(this.chatId, this.participant, rights);\n };\n\n this.eventListener.addEventListener('destroy', destroyListener);\n\n this.scrollable.append(section.container);\n }\n \n {\n const section = new SettingSection({});\n\n if(this.participant._ === 'channelParticipantBanned') {\n const btnDeleteException = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'GroupPermission.Delete'});\n\n attachClickEvent(btnDeleteException, () => {\n const toggle = toggleDisability([btnDeleteException], true);\n appChatsManager.clearChannelParticipantBannedRights(this.chatId, this.participant).then(() => {\n this.eventListener.removeEventListener('destroy', destroyListener);\n this.close();\n }, () => {\n toggle();\n });\n }, {listenerSetter: this.listenerSetter});\n \n section.content.append(btnDeleteException);\n }\n\n const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'deleteuser', text: 'UserRestrictionsBlock'});\n\n attachClickEvent(btnDelete, () => {\n const toggle = toggleDisability([btnDelete], true);\n appChatsManager.kickFromChannel(this.chatId, this.participant).then(() => {\n this.eventListener.removeEventListener('destroy', destroyListener);\n this.close();\n });\n /* new PopupPeer('popup-group-kick-user', {\n peerId: -this.chatId,\n title: 'Ban User?',\n description: `Are you sure you want to ban <b>${appPeersManager.getPeerTitle(this.userId)}</b>`,\n buttons: addCancelButton([{\n text: 'BAN',\n callback: () => {\n const toggle = toggleDisability([btnDelete], true);\n\n appChatsManager.kickFromChannel(this.chatId, this.participant).then(() => {\n this.eventListener.removeEventListener('destroy', destroyListener);\n this.close();\n }, () => {\n toggle();\n });\n },\n isDanger: true\n }])\n }).show(); */\n }, {listenerSetter: this.listenerSetter});\n\n section.content.append(btnDelete);\n\n this.scrollable.append(section.container);\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { attachClickEvent, replaceContent } from \"../../../helpers/dom\";\nimport findUpTag from \"../../../helpers/dom/findUpTag\";\nimport ListenerSetter from \"../../../helpers/listenerSetter\";\nimport ScrollableLoader from \"../../../helpers/listLoader\";\nimport { ChannelParticipant, Chat, ChatBannedRights, Update } from \"../../../layer\";\nimport appChatsManager, { ChatRights } from \"../../../lib/appManagers/appChatsManager\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport I18n, { i18n, join, LangPackKey } from \"../../../lib/langPack\";\nimport rootScope from \"../../../lib/rootScope\";\nimport CheckboxField from \"../../checkboxField\";\nimport PopupPickUser from \"../../popups/pickUser\";\nimport Row from \"../../row\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport { SliderSuperTabEventable } from \"../../sliderTab\";\nimport { toast } from \"../../toast\";\nimport AppUserPermissionsTab from \"./userPermissions\";\n\nexport class ChatPermissions {\n public v: Array<{\n flags: ChatRights[],\n text: LangPackKey,\n exceptionText: LangPackKey,\n checkboxField?: CheckboxField,\n }>;\n private toggleWith: Partial<{[chatRight in ChatRights]: ChatRights[]}>;\n\n constructor(options: {\n chatId: number,\n listenerSetter: ListenerSetter,\n appendTo: HTMLElement,\n participant?: ChannelParticipant.channelParticipantBanned\n }) {\n this.v = [\n {flags: ['send_messages'], text: 'UserRestrictionsSend', exceptionText: 'UserRestrictionsNoSend'},\n {flags: ['send_media'], text: 'UserRestrictionsSendMedia', exceptionText: 'UserRestrictionsNoSendMedia'},\n {flags: ['send_stickers', 'send_gifs'], text: 'UserRestrictionsSendStickers', exceptionText: 'UserRestrictionsNoSendStickers'},\n {flags: ['send_polls'], text: 'UserRestrictionsSendPolls', exceptionText: 'UserRestrictionsNoSendPolls'},\n {flags: ['embed_links'], text: 'UserRestrictionsEmbedLinks', exceptionText: 'UserRestrictionsNoEmbedLinks'},\n {flags: ['invite_users'], text: 'UserRestrictionsInviteUsers', exceptionText: 'UserRestrictionsNoInviteUsers'},\n {flags: ['pin_messages'], text: 'UserRestrictionsPinMessages', exceptionText: 'UserRestrictionsNoPinMessages'},\n {flags: ['change_info'], text: 'UserRestrictionsChangeInfo', exceptionText: 'UserRestrictionsNoChangeInfo'}\n ];\n\n this.toggleWith = {\n 'send_messages': ['send_media', 'send_stickers', 'send_polls', 'embed_links']\n };\n\n const chat: Chat.chat = appChatsManager.getChat(options.chatId);\n const defaultBannedRights = chat.default_banned_rights;\n const rights = options.participant ? appChatsManager.combineParticipantBannedRights(options.chatId, options.participant.banned_rights) : defaultBannedRights;\n \n for(const info of this.v) {\n const mainFlag = info.flags[0];\n info.checkboxField = new CheckboxField({\n text: info.text,\n checked: appChatsManager.hasRights(options.chatId, mainFlag, rights),\n restriction: true,\n withRipple: true\n });\n\n // @ts-ignore\n if(options.participant && defaultBannedRights.pFlags[mainFlag]) {\n info.checkboxField.input.disabled = true;\n \n /* options.listenerSetter.add(info.checkboxField.input, 'change', (e) => {\n if(!e.isTrusted) {\n return;\n }\n\n cancelEvent(e);\n toast('This option is disabled for all members in Group Permissions.');\n info.checkboxField.checked = false;\n }); */\n\n attachClickEvent(info.checkboxField.label, (e) => {\n toast(I18n.format('UserRestrictionsDisabled', true));\n }, {listenerSetter: options.listenerSetter});\n }\n\n if(this.toggleWith[mainFlag]) {\n options.listenerSetter.add(info.checkboxField.input, 'change', () => {\n if(!info.checkboxField.checked) {\n const other = this.v.filter(i => this.toggleWith[mainFlag].includes(i.flags[0]));\n other.forEach(info => {\n info.checkboxField.checked = false;\n });\n }\n });\n }\n\n options.appendTo.append(info.checkboxField.label);\n }\n }\n\n public takeOut() {\n const rights: ChatBannedRights = {\n _: 'chatBannedRights',\n until_date: 0x7FFFFFFF,\n pFlags: {}\n };\n\n for(const info of this.v) {\n const banned = !info.checkboxField.checked;\n if(banned) {\n info.flags.forEach(flag => {\n // @ts-ignore\n rights.pFlags[flag] = true;\n });\n }\n }\n\n return rights;\n }\n}\n\nexport default class AppGroupPermissionsTab extends SliderSuperTabEventable {\n public chatId: number;\n\n protected async init() {\n this.container.classList.add('edit-peer-container', 'group-permissions-container');\n this.setTitle('ChannelPermissions');\n\n let chatPermissions: ChatPermissions;\n {\n const section = new SettingSection({\n name: 'ChannelPermissionsHeader',\n });\n\n chatPermissions = new ChatPermissions({\n chatId: this.chatId,\n listenerSetter: this.listenerSetter,\n appendTo: section.content,\n });\n\n this.eventListener.addEventListener('destroy', () => {\n appChatsManager.editChatDefaultBannedRights(this.chatId, chatPermissions.takeOut());\n });\n\n this.scrollable.append(section.container);\n }\n \n {\n const section = new SettingSection({\n name: 'PrivacyExceptions'\n });\n\n const addExceptionRow = new Row({\n titleLangKey: 'ChannelAddException',\n subtitleLangKey: 'Loading',\n icon: 'adduser',\n clickable: () => {\n new PopupPickUser({\n peerTypes: ['channelParticipants'],\n onSelect: (peerId) => {\n setTimeout(() => {\n openPermissions(peerId);\n }, 0);\n },\n placeholder: 'ExceptionModal.Search.Placeholder',\n peerId: -this.chatId,\n });\n }\n });\n\n const openPermissions = async(peerId: number) => {\n let participant: AppUserPermissionsTab['participant'];\n try {\n participant = await appProfileManager.getChannelParticipant(this.chatId, peerId) as any;\n } catch(err) {\n toast('User is no longer participant');\n return;\n }\n\n const tab = new AppUserPermissionsTab(this.slider);\n tab.participant = participant;\n tab.chatId = this.chatId;\n tab.userId = peerId;\n tab.open();\n };\n\n section.content.append(addExceptionRow.container);\n\n /* const removedUsersRow = new Row({\n titleLangKey: 'ChannelBlockedUsers',\n subtitleLangKey: 'NoBlockedUsers',\n icon: 'deleteuser',\n clickable: true\n });\n\n section.content.append(removedUsersRow.container); */\n\n const c = section.generateContentElement();\n c.classList.add('chatlist-container');\n \n const list = appDialogsManager.createChatList();\n c.append(list);\n\n attachClickEvent(list, (e) => {\n const target = findUpTag(e.target, 'LI');\n if(!target) return;\n\n const peerId = +target.dataset.peerId;\n openPermissions(peerId);\n }, {listenerSetter: this.listenerSetter});\n\n const setSubtitle = (li: Element, participant: ChannelParticipant.channelParticipantBanned) => {\n const bannedRights = participant.banned_rights;//appChatsManager.combineParticipantBannedRights(this.chatId, participant.banned_rights);\n const defaultBannedRights = (appChatsManager.getChat(this.chatId) as Chat.channel).default_banned_rights;\n //const combinedRights = appChatsManager.combineParticipantBannedRights(this.chatId, bannedRights);\n\n const cantWhat: LangPackKey[] = []/* , canWhat: LangPackKey[] = [] */;\n chatPermissions.v.forEach(info => {\n const mainFlag = info.flags[0];\n // @ts-ignore\n if(bannedRights.pFlags[mainFlag] && !defaultBannedRights.pFlags[mainFlag]) {\n cantWhat.push(info.exceptionText);\n // @ts-ignore\n }/* else if(!combinedRights.pFlags[mainFlag]) {\n canWhat.push(info.exceptionText);\n } */\n });\n\n const el = li.querySelector('.user-last-message') as HTMLElement;\n\n if(cantWhat.length) {\n el.innerHTML = '';\n el.append(...join(cantWhat.map(t => i18n(t)), false));\n }/* else if(canWhat.length) {\n str = 'Can ' + canWhat.join(canWhat.length === 2 ? ' and ' : ', ');\n } */\n \n el.classList.toggle('hide', !cantWhat.length);\n };\n\n const add = (participant: ChannelParticipant.channelParticipantBanned, append: boolean) => {\n const {dom} = appDialogsManager.addDialogNew({\n dialog: participant.user_id,\n container: list,\n drawStatus: false,\n rippleEnabled: true,\n avatarSize: 48,\n append\n });\n\n setSubtitle(dom.listEl, participant);\n\n //dom.titleSpan.innerHTML = 'Chinaza Akachi';\n //dom.lastMessageSpan.innerHTML = 'Can Add Users and Pin Messages';\n };\n\n this.listenerSetter.add(rootScope, 'apiUpdate', (update: Update) => {\n if(update._ === 'updateChannelParticipant') {\n const needAdd = update.new_participant?._ === 'channelParticipantBanned' && !update.new_participant.banned_rights.pFlags.view_messages;\n const li = list.querySelector(`[data-peer-id=\"${update.user_id}\"]`);\n if(needAdd) {\n if(!li) {\n add(update.new_participant as ChannelParticipant.channelParticipantBanned, false);\n } else {\n setSubtitle(li, update.new_participant as ChannelParticipant.channelParticipantBanned);\n }\n\n if(update.prev_participant?._ !== 'channelParticipantBanned') {\n ++exceptionsCount;\n }\n } else {\n if(li) {\n li.remove();\n }\n\n if(update.prev_participant?._ === 'channelParticipantBanned') {\n --exceptionsCount;\n }\n }\n\n setLength();\n }\n });\n\n const setLength = () => {\n replaceContent(addExceptionRow.subtitle, i18n(exceptionsCount ? 'Permissions.ExceptionsCount' : 'Permissions.NoExceptions', [exceptionsCount]));\n };\n\n let exceptionsCount = 0;\n const LOAD_COUNT = 50;\n const loader = new ScrollableLoader({\n scrollable: this.scrollable,\n getPromise: () => {\n return appProfileManager.getChannelParticipants(this.chatId, {_: 'channelParticipantsBanned', q: ''}, LOAD_COUNT, list.childElementCount).then(res => {\n for(const participant of res.participants) {\n add(participant as ChannelParticipant.channelParticipantBanned, true);\n }\n\n exceptionsCount = res.count;\n setLength();\n\n return res.participants.length < LOAD_COUNT || res.count === list.childElementCount;\n });\n }\n });\n\n this.scrollable.append(section.container);\n\n await loader.load();\n }\n }\n\n onOpenAfterTimeout() {\n this.scrollable.onScroll();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appChatsManager from \"../../lib/appManagers/appChatsManager\";\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport appPeersManager, { PeerType } from \"../../lib/appManagers/appPeersManager\";\nimport { LangPackKey } from \"../../lib/langPack\";\nimport PeerTitle from \"../peerTitle\";\nimport PopupPeer, { PopupPeerButtonCallbackCheckboxes, PopupPeerOptions } from \"./peer\";\n\nexport default class PopupDeleteDialog {\n constructor(peerId: number, peerType: PeerType = appPeersManager.getDialogType(peerId), onSelect?: (promise: Promise<any>) => void) {\n const peerTitleElement = new PeerTitle({\n peerId,\n onlyFirstName: true\n }).element;\n\n /* const callbackFlush = (checked: PopupPeerButtonCallbackCheckboxes) => {\n const promise = appMessagesManager.flushHistory(peerId, checkboxes ? !checked[checkboxes[0].text] : undefined);\n onSelect && onSelect(promise);\n }; */\n\n const callbackLeave = (checked: PopupPeerButtonCallbackCheckboxes) => {\n const promise = appChatsManager.leave(-peerId);\n onSelect && onSelect(promise);\n };\n\n const callbackDelete = (checked: PopupPeerButtonCallbackCheckboxes) => {\n let promise: Promise<any>;\n\n if(peerId > 0) {\n promise = appMessagesManager.flushHistory(peerId, false, checkboxes ? checked[checkboxes[0].text] : undefined);\n } else {\n if(checked[checkboxes[0].text]) {\n promise = appChatsManager.delete(-peerId);\n } else {\n promise = appChatsManager.leave(-peerId);\n }\n }\n \n onSelect && onSelect(promise);\n };\n\n let title: LangPackKey, description: LangPackKey, descriptionArgs: any[], buttons: PopupPeerOptions['buttons'], checkboxes: PopupPeerOptions['checkboxes'];\n switch(peerType) {\n case 'channel': {\n title = 'LeaveChannelMenu';\n description = 'ChannelLeaveAlertWithName';\n descriptionArgs = [peerTitleElement];\n buttons = [{\n langKey: 'LeaveChannel',\n isDanger: true,\n callback: callbackLeave\n }];\n\n break;\n }\n\n /* case 'megagroup': {\n title = 'Leave Group?';\n description = `Are you sure you want to leave this group?`;\n buttons = [{\n text: 'LEAVE ' + peerTitleElement,\n isDanger: true,\n callback: callbackLeave\n }];\n\n break;\n } */\n\n case 'chat': {\n title = 'DeleteChatUser';\n description = 'AreYouSureDeleteThisChatWithUser';\n descriptionArgs = [peerTitleElement];\n\n checkboxes = [{\n text: 'DeleteMessagesOptionAlso',\n textArgs: [\n new PeerTitle({\n peerId,\n onlyFirstName: true\n }).element\n ]\n }];\n\n buttons = [{\n langKey: 'DeleteChatUser',\n isDanger: true,\n callback: callbackDelete\n }];\n\n break;\n }\n\n case 'saved': {\n title = 'DeleteChatUser';\n description = 'AreYouSureDeleteThisChatSavedMessages';\n buttons = [{\n langKey: 'DeleteChatUser',\n isDanger: true,\n callback: callbackDelete\n }];\n\n break;\n }\n\n case 'megagroup':\n case 'group': {\n if(appChatsManager.hasRights(-peerId, 'delete_chat')) {\n title = 'DeleteMegaMenu';\n description = 'AreYouSureDeleteAndExit';\n buttons = [{\n langKey: 'DeleteMegaMenu',\n isDanger: true,\n callback: callbackDelete\n }];\n\n checkboxes = [{\n text: 'DeleteChat.DeleteGroupForAll'\n }];\n } else {\n title = 'LeaveMegaMenu';\n description = 'AreYouSureDeleteAndExitName';\n descriptionArgs = [peerTitleElement];\n buttons = [{\n langKey: 'DeleteChatUser',\n isDanger: true,\n callback: callbackLeave\n }];\n }\n\n break;\n }\n }\n\n new PopupPeer('popup-delete-chat', {\n peerId,\n titleLangKey: title,\n descriptionLangKey: description,\n descriptionLangArgs: descriptionArgs,\n buttons,\n checkboxes\n }).show();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\"\nimport InputField from \"../../inputField\";\nimport EditPeer from \"../../editPeer\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport Row from \"../../row\";\nimport Button from \"../../button\";\nimport appChatsManager, { ChatRights } from \"../../../lib/appManagers/appChatsManager\";\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport { ChatFull } from \"../../../layer\";\nimport AppGroupTypeTab from \"./groupType\";\nimport rootScope from \"../../../lib/rootScope\";\nimport AppGroupPermissionsTab from \"./groupPermissions\";\nimport { i18n } from \"../../../lib/langPack\";\nimport PopupDeleteDialog from \"../../popups/deleteDialog\";\n\nexport default class AppEditGroupTab extends SliderSuperTab {\n private groupNameInputField: InputField;\n private descriptionInputField: InputField;\n private editPeer: EditPeer;\n public chatId: number;\n\n protected async _init() {\n // * cleanup prev\n this.listenerSetter.removeAll();\n this.scrollable.container.innerHTML = '';\n\n this.container.classList.add('edit-peer-container', 'edit-group-container');\n this.setTitle('Edit');\n\n const chatFull = await appProfileManager.getChatFull(this.chatId, true);\n\n {\n const section = new SettingSection({noDelimiter: true});\n const inputFields: InputField[] = [];\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n \n this.groupNameInputField = new InputField({\n label: 'CreateGroup.NameHolder',\n name: 'group-name',\n maxLength: 255\n });\n this.descriptionInputField = new InputField({\n label: 'DescriptionPlaceholder',\n name: 'group-description',\n maxLength: 255\n });\n\n const chat = appChatsManager.getChat(this.chatId);\n \n this.groupNameInputField.setOriginalValue(chat.title);\n\n this.descriptionInputField.setOriginalValue(chatFull.about);\n\n inputWrapper.append(this.groupNameInputField.container, this.descriptionInputField.container);\n \n inputFields.push(this.groupNameInputField, this.descriptionInputField);\n\n this.editPeer = new EditPeer({\n peerId: -this.chatId,\n inputFields,\n listenerSetter: this.listenerSetter\n });\n this.content.append(this.editPeer.nextBtn);\n\n section.content.append(this.editPeer.avatarEdit.container, inputWrapper);\n\n if(appChatsManager.hasRights(this.chatId, 'change_type')) {\n const groupTypeRow = new Row({\n titleLangKey: 'GroupType',\n clickable: () => {\n const tab = new AppGroupTypeTab(this.slider);\n tab.peerId = -this.chatId;\n tab.chatFull = chatFull;\n tab.open();\n\n this.listenerSetter.add(tab.eventListener, 'destroy', setGroupTypeSubtitle);\n },\n icon: 'lock'\n });\n\n const setGroupTypeSubtitle = () => {\n groupTypeRow.subtitle.textContent = '';\n groupTypeRow.subtitle.append(i18n(chat.username ? 'TypePublicGroup' : 'TypePrivateGroup'));\n };\n\n setGroupTypeSubtitle();\n section.content.append(groupTypeRow.container);\n }\n\n if(appChatsManager.hasRights(this.chatId, 'change_permissions')) {\n const flags = [\n 'send_messages',\n 'send_media',\n 'send_stickers',\n 'send_polls',\n 'embed_links',\n 'invite_users',\n 'pin_messages',\n 'change_info'\n ] as ChatRights[];\n\n const permissionsRow = new Row({\n titleLangKey: 'ChannelPermissions',\n clickable: () => {\n const tab = new AppGroupPermissionsTab(this.slider);\n tab.chatId = this.chatId;\n tab.open();\n },\n icon: 'permissions',\n });\n\n const setPermissionsLength = () => {\n permissionsRow.subtitle.innerHTML = flags.reduce((acc, f) => acc + +appChatsManager.hasRights(this.chatId, f, chat.default_banned_rights), 0) + '/' + flags.length;\n };\n\n setPermissionsLength(); \n section.content.append(permissionsRow.container);\n\n this.listenerSetter.add(rootScope, 'chat_update', (chatId) => {\n if(this.chatId === chatId) {\n setPermissionsLength();\n }\n });\n }\n\n /* const administratorsRow = new Row({\n titleLangKey: 'PeerInfo.Administrators',\n subtitle: '' + ((chatFull as ChatFull.channelFull).admins_count || 1),\n icon: 'admin',\n clickable: true\n });\n\n section.content.append(administratorsRow.container); */\n\n this.scrollable.append(section.container);\n\n attachClickEvent(this.editPeer.nextBtn, () => {\n this.editPeer.nextBtn.disabled = true;\n \n let promises: Promise<any>[] = [];\n\n const id = this.chatId;\n if(this.groupNameInputField.isValid()) {\n promises.push(appChatsManager.editTitle(id, this.groupNameInputField.value));\n }\n\n if(this.descriptionInputField.isValid()) {\n promises.push(appChatsManager.editAbout(id, this.descriptionInputField.value));\n }\n\n if(this.editPeer.uploadAvatar) {\n promises.push(this.editPeer.uploadAvatar().then(inputFile => {\n return appChatsManager.editPhoto(id, inputFile);\n }));\n }\n \n Promise.race(promises).finally(() => {\n this.editPeer.nextBtn.removeAttribute('disabled');\n this.close();\n });\n }, {listenerSetter: this.listenerSetter});\n }\n\n /* {\n const section = new SettingSection({\n\n });\n\n const membersRow = new Row({\n titleLangKey: 'GroupMembers',\n subtitle: '2 500',\n icon: 'newgroup',\n clickable: true\n });\n\n section.content.append(membersRow.container);\n\n if(appChatsManager.hasRights(this.chatId, 'change_permissions')) {\n const showChatHistoryCheckboxField = new CheckboxField({\n text: 'Show chat history for new members',\n withRipple: true\n });\n \n if(appChatsManager.isChannel(this.chatId) && !(chatFull as ChatFull.channelFull).pFlags.hidden_prehistory) {\n showChatHistoryCheckboxField.checked = true;\n }\n \n section.content.append(showChatHistoryCheckboxField.label);\n }\n\n this.scrollable.append(section.container);\n } */\n\n if(appChatsManager.hasRights(this.chatId, 'delete_chat')) {\n const section = new SettingSection({});\n\n const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'DeleteMega'});\n\n attachClickEvent(btnDelete, () => {\n new PopupDeleteDialog(-this.chatId, undefined, (promise) => {\n const toggle = toggleDisability([btnDelete], true);\n promise.then(() => {\n this.close();\n }, () => {\n toggle();\n });\n });\n }, {listenerSetter: this.listenerSetter});\n\n section.content.append(btnDelete);\n\n this.scrollable.append(section.container);\n }\n\n // ! this one will fire earlier than tab's closeAfterTimeout (destroy) event and listeners will be erased, so destroy won't fire\n this.listenerSetter.add(rootScope, 'dialog_migrate', ({migrateFrom, migrateTo}) => {\n if(-this.chatId === migrateFrom) {\n this.chatId = -migrateTo;\n this._init();\n }\n });\n }\n\n protected init() {\n return this._init();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\"\nimport InputField from \"../../inputField\";\nimport EditPeer from \"../../editPeer\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport Row from \"../../row\";\nimport CheckboxField from \"../../checkboxField\";\nimport Button from \"../../button\";\nimport appChatsManager from \"../../../lib/appManagers/appChatsManager\";\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport PopupPeer from \"../../popups/peer\";\nimport { addCancelButton } from \"../../popups\";\nimport { i18n } from \"../../../lib/langPack\";\nimport { numberThousandSplitter } from \"../../../helpers/number\";\n\nexport default class AppEditChannelTab extends SliderSuperTab {\n private nameInputField: InputField;\n private descriptionInputField: InputField;\n private editPeer: EditPeer;\n public peerId: number;\n\n protected async init() {\n this.container.classList.add('edit-peer-container', 'edit-channel-container');\n this.setTitle('Edit');\n\n const chatFull = await appProfileManager.getChannelFull(-this.peerId, true);\n\n {\n const section = new SettingSection({noDelimiter: true});\n\n if(appChatsManager.hasRights(-this.peerId, 'change_info')) {\n const inputFields: InputField[] = [];\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n \n this.nameInputField = new InputField({\n label: 'Channel.ChannelNameHolder',\n name: 'channel-name',\n maxLength: 255\n });\n this.descriptionInputField = new InputField({\n label: 'DescriptionPlaceholder',\n name: 'channel-description',\n maxLength: 255\n });\n \n this.nameInputField.setOriginalValue(appChatsManager.getChat(-this.peerId).title);\n\n this.descriptionInputField.setOriginalValue(chatFull.about);\n\n inputWrapper.append(this.nameInputField.container, this.descriptionInputField.container);\n \n inputFields.push(this.nameInputField, this.descriptionInputField);\n\n this.editPeer = new EditPeer({\n peerId: this.peerId,\n inputFields,\n listenerSetter: this.listenerSetter\n });\n this.content.append(this.editPeer.nextBtn);\n\n section.content.append(this.editPeer.avatarEdit.container, inputWrapper);\n\n attachClickEvent(this.editPeer.nextBtn, () => {\n this.editPeer.nextBtn.disabled = true;\n \n let promises: Promise<any>[] = [];\n \n const id = -this.peerId;\n if(this.nameInputField.isValid()) {\n promises.push(appChatsManager.editTitle(id, this.nameInputField.value));\n }\n \n if(this.descriptionInputField.isValid()) {\n promises.push(appChatsManager.editAbout(id, this.descriptionInputField.value));\n }\n \n if(this.editPeer.uploadAvatar) {\n promises.push(this.editPeer.uploadAvatar().then(inputFile => {\n return appChatsManager.editPhoto(id, inputFile);\n }));\n }\n \n Promise.race(promises).finally(() => {\n this.editPeer.nextBtn.removeAttribute('disabled');\n this.close();\n });\n }, {listenerSetter: this.listenerSetter});\n }\n\n /* if(appChatsManager.hasRights(-this.peerId, 'change_type')) {\n const channelTypeRow = new Row({\n titleLangKey: 'ChannelType',\n subtitleLangKey: 'TypePrivate',\n clickable: true,\n icon: 'lock'\n });\n \n section.content.append(channelTypeRow.container);\n }\n\n if(appChatsManager.hasRights(-this.peerId, 'change_info')) {\n const discussionRow = new Row({\n titleLangKey: 'PeerInfo.Discussion',\n subtitleLangKey: 'PeerInfo.Discussion.Add',\n clickable: true,\n icon: 'message'\n });\n\n section.content.append(discussionRow.container);\n }\n\n const administratorsRow = new Row({\n titleLangKey: 'PeerInfo.Administrators',\n subtitle: '' + chatFull.admins_count,\n icon: 'admin',\n clickable: true\n });\n\n section.content.append(administratorsRow.container);\n\n if(appChatsManager.hasRights(-this.peerId, 'change_info')) {\n const signMessagesCheckboxField = new CheckboxField({\n text: 'PeerInfo.SignMessages',\n checked: false\n });\n\n section.content.append(signMessagesCheckboxField.label);\n } */\n\n this.scrollable.append(section.container);\n }\n\n /* {\n const section = new SettingSection({\n\n });\n\n const subscribersRow = new Row({\n titleLangKey: 'PeerInfo.Subscribers',\n icon: 'newgroup',\n clickable: true\n });\n\n subscribersRow.subtitle.append(i18n('Subscribers', [numberThousandSplitter(335356)]));\n\n section.content.append(subscribersRow.container);\n\n this.scrollable.append(section.container);\n } */\n\n if(appChatsManager.hasRights(-this.peerId, 'delete_chat')) {\n const section = new SettingSection({\n \n });\n\n const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'PeerInfo.DeleteChannel'});\n\n attachClickEvent(btnDelete, () => {\n new PopupPeer('popup-delete-channel', {\n peerId: this.peerId,\n titleLangKey: 'ChannelDeleteMenu',\n descriptionLangKey: 'AreYouSureDeleteAndExitChannel',\n buttons: addCancelButton([{\n langKey: 'ChannelDeleteMenu',\n callback: () => {\n const toggle = toggleDisability([btnDelete], true);\n\n },\n isDanger: true\n }, {\n langKey: 'DeleteChannelForAll',\n callback: () => {\n const toggle = toggleDisability([btnDelete], true);\n\n appChatsManager.deleteChannel(-this.peerId).then(() => {\n this.close();\n }, () => {\n toggle();\n });\n },\n isDanger: true\n }])\n }).show();\n }, {listenerSetter: this.listenerSetter});\n\n section.content.append(btnDelete);\n\n this.scrollable.append(section.container);\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\"\nimport InputField from \"../../inputField\";\nimport EditPeer from \"../../editPeer\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport Row from \"../../row\";\nimport CheckboxField from \"../../checkboxField\";\nimport Button from \"../../button\";\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport appNotificationsManager from \"../../../lib/appManagers/appNotificationsManager\";\nimport PeerTitle from \"../../peerTitle\";\nimport appMessagesManager from \"../../../lib/appManagers/appMessagesManager\";\nimport rootScope from \"../../../lib/rootScope\";\nimport appPeersManager from \"../../../lib/appManagers/appPeersManager\";\nimport PopupPeer from \"../../popups/peer\";\nimport { addCancelButton } from \"../../popups\";\nimport { i18n } from \"../../../lib/langPack\";\n\nexport default class AppEditContactTab extends SliderSuperTab {\n private nameInputField: InputField;\n private lastNameInputField: InputField;\n private editPeer: EditPeer;\n public peerId: number;\n\n protected init() {\n this.container.classList.add('edit-peer-container', 'edit-contact-container');\n this.setTitle('Edit');\n\n {\n const section = new SettingSection({noDelimiter: true});\n const inputFields: InputField[] = [];\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n \n this.nameInputField = new InputField({\n label: 'EditProfile.FirstNameLabel',\n name: 'contact-name',\n maxLength: 70\n });\n this.lastNameInputField = new InputField({\n label: 'Login.Register.LastName.Placeholder',\n name: 'contact-lastname',\n maxLength: 70\n });\n \n const user = appUsersManager.getUser(this.peerId);\n\n this.nameInputField.setOriginalValue(user.first_name);\n this.lastNameInputField.setOriginalValue(user.last_name);\n\n inputWrapper.append(this.nameInputField.container, this.lastNameInputField.container);\n \n inputFields.push(this.nameInputField, this.lastNameInputField);\n\n this.editPeer = new EditPeer({\n peerId: this.peerId,\n inputFields,\n listenerSetter: this.listenerSetter,\n doNotEditAvatar: true\n });\n this.content.append(this.editPeer.nextBtn);\n\n const div = document.createElement('div');\n div.classList.add('avatar-edit');\n div.append(this.editPeer.avatarElem);\n\n const notificationsCheckboxField = new CheckboxField({\n text: 'Notifications'\n });\n\n notificationsCheckboxField.input.addEventListener('change', (e) => {\n if(!e.isTrusted) {\n return;\n }\n\n appMessagesManager.mutePeer(this.peerId);\n });\n\n this.listenerSetter.add(rootScope, 'notify_settings', (update) => {\n if(update.peer._ !== 'notifyPeer') return;\n const peerId = appPeersManager.getPeerId(update.peer.peer);\n if(this.peerId === peerId) {\n const enabled = !appNotificationsManager.isMuted(update.notify_settings);\n if(enabled !== notificationsCheckboxField.checked) {\n notificationsCheckboxField.checked = enabled;\n }\n }\n });\n\n const notificationsRow = new Row({\n checkboxField: notificationsCheckboxField\n });\n\n const enabled = !appNotificationsManager.isPeerLocalMuted(this.peerId, false);\n notificationsCheckboxField.checked = enabled;\n\n const profileNameDiv = document.createElement('div');\n profileNameDiv.classList.add('profile-name');\n profileNameDiv.append(new PeerTitle({\n peerId: this.peerId\n }).element);\n //profileNameDiv.innerHTML = 'Karen Stanford';\n\n const profileSubtitleDiv = document.createElement('div');\n profileSubtitleDiv.classList.add('profile-subtitle');\n profileSubtitleDiv.append(i18n('EditContact.OriginalName'));\n\n section.content.append(div, profileNameDiv, profileSubtitleDiv, inputWrapper, notificationsRow.container);\n\n this.scrollable.append(section.container);\n\n attachClickEvent(this.editPeer.nextBtn, () => {\n this.editPeer.nextBtn.disabled = true;\n\n appUsersManager.addContact(this.peerId, this.nameInputField.value, this.lastNameInputField.value, appUsersManager.getUser(this.peerId).phone)\n .finally(() => {\n this.editPeer.nextBtn.removeAttribute('disabled');\n this.close();\n });\n }, {listenerSetter: this.listenerSetter});\n }\n\n {\n const section = new SettingSection({\n \n });\n\n const btnDelete = Button('btn-primary btn-transparent danger', {icon: 'delete', text: 'PeerInfo.DeleteContact'});\n\n attachClickEvent(btnDelete, () => {\n new PopupPeer('popup-delete-contact', {\n peerId: this.peerId,\n titleLangKey: 'DeleteContact',\n descriptionLangKey: 'AreYouSureDeleteContact',\n buttons: addCancelButton([{\n langKey: 'Delete',\n callback: () => {\n const toggle = toggleDisability([btnDelete], true);\n\n appUsersManager.deleteContacts([this.peerId]).then(() => {\n this.close();\n }, () => {\n toggle();\n });\n },\n isDanger: true\n }])\n }).show();\n }, {listenerSetter: this.listenerSetter});\n\n section.content.append(btnDelete);\n\n this.scrollable.append(section.container);\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { cancelEvent } from \"../helpers/dom\";\nimport { safeAssign } from \"../helpers/object\";\nimport { isTouchSupported } from \"../helpers/touchSupport\";\n\nconst getEvent = (e: TouchEvent | MouseEvent) => {\n return (e as TouchEvent).touches ? (e as TouchEvent).touches[0] : e as MouseEvent;\n};\n\nconst attachGlobalListenerTo = window;\n\nexport default class SwipeHandler {\n private element: HTMLElement;\n private onSwipe: (xDiff: number, yDiff: number) => boolean;\n private verifyTouchTarget: (evt: TouchEvent | MouseEvent) => boolean;\n private onFirstSwipe: () => void;\n private onReset: () => void;\n\n private hadMove = false;\n private xDown: number = null;\n private yDown: number = null;\n\n constructor(options: {\n element: SwipeHandler['element'],\n onSwipe: SwipeHandler['onSwipe'],\n verifyTouchTarget?: SwipeHandler['verifyTouchTarget'],\n onFirstSwipe?: SwipeHandler['onFirstSwipe'],\n onReset?: SwipeHandler['onReset'],\n }) {\n safeAssign(this, options);\n\n if(!isTouchSupported) {\n this.element.addEventListener('mousedown', this.handleStart, false);\n attachGlobalListenerTo.addEventListener('mouseup', this.reset);\n } else {\n this.element.addEventListener('touchstart', this.handleStart, false);\n attachGlobalListenerTo.addEventListener('touchend', this.reset);\n }\n }\n\n reset = (e?: Event) => {\n /* if(e) {\n cancelEvent(e);\n } */\n\n if(isTouchSupported) {\n attachGlobalListenerTo.removeEventListener('touchmove', this.handleMove, {capture: true});\n } else {\n attachGlobalListenerTo.removeEventListener('mousemove', this.handleMove);\n this.element.style.cursor = '';\n }\n\n if(this.onReset && this.hadMove) {\n this.onReset();\n }\n\n this.xDown = this.yDown = null;\n this.hadMove = false;\n };\n\n handleStart = (_e: TouchEvent | MouseEvent) => {\n const e = getEvent(_e);\n if(this.verifyTouchTarget && !this.verifyTouchTarget(_e)) {\n return this.reset();\n }\n\n this.xDown = e.clientX;\n this.yDown = e.clientY;\n\n if(isTouchSupported) {\n attachGlobalListenerTo.addEventListener('touchmove', this.handleMove, {passive: false, capture: true});\n } else {\n attachGlobalListenerTo.addEventListener('mousemove', this.handleMove, false);\n }\n };\n\n handleMove = (_e: TouchEvent | MouseEvent) => {\n if(this.xDown === null || this.yDown === null) {\n return this.reset();\n }\n\n cancelEvent(_e);\n\n const e = getEvent(_e);\n const xUp = e.clientX;\n const yUp = e.clientY;\n\n const xDiff = this.xDown - xUp;\n const yDiff = this.yDown - yUp;\n\n if(!this.hadMove) {\n if(!xDiff && !yDiff) {\n return;\n }\n\n this.hadMove = true;\n\n if(!isTouchSupported) {\n this.element.style.cursor = 'grabbing';\n }\n\n if(this.onFirstSwipe) {\n this.onFirstSwipe();\n }\n }\n\n // if(Math.abs(xDiff) > Math.abs(yDiff)) { /*most significant*/\n // if(xDiff > 0) { /* left swipe */ \n\n // } else { /* right swipe */\n\n // } \n // } else {\n // if(yDiff > 0) { /* up swipe */ \n \n // } else { /* down swipe */\n \n // }\n // }\n\n /* reset values */\n if(this.onSwipe(xDiff, yDiff)) {\n this.reset();\n }\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport AppSelectPeers from \"../../appSelectPeers\";\nimport { putPreloader } from \"../../misc\";\nimport Button from \"../../button\";\nimport { LangPackKey, _i18n } from \"../../../lib/langPack\";\n\nexport default class AppAddMembersTab extends SliderSuperTab {\n private nextBtn: HTMLButtonElement;\n private selector: AppSelectPeers;\n private peerType: 'channel' | 'chat' | 'privacy';\n private takeOut: (peerIds: number[]) => Promise<any> | false | void;\n private skippable: boolean;\n\n protected init() {\n this.nextBtn = Button('btn-corner btn-circle', {icon: 'arrow_next'});\n this.content.append(this.nextBtn);\n \n this.nextBtn.addEventListener('click', () => {\n const peerIds = this.selector.getSelected();\n\n if(this.skippable) {\n this.takeOut(peerIds);\n this.close();\n } else {\n const promise = this.takeOut(peerIds);\n\n if(promise instanceof Promise) {\n this.attachToPromise(promise);\n } else if(promise === undefined) {\n this.close();\n }\n }\n });\n }\n\n public attachToPromise(promise: Promise<any>) {\n this.nextBtn.classList.remove('tgico-arrow_next');\n this.nextBtn.disabled = true;\n putPreloader(this.nextBtn);\n this.selector.freezed = true;\n\n promise.then(() => {\n this.close();\n });\n }\n\n public open(options: {\n title: LangPackKey,\n placeholder: LangPackKey,\n peerId?: number, \n type: AppAddMembersTab['peerType'], \n takeOut?: AppAddMembersTab['takeOut'],\n skippable: boolean,\n selectedPeerIds?: number[]\n }) {\n const ret = super.open();\n\n this.setTitle(options.title);\n this.peerType = options.type;\n this.takeOut = options.takeOut;\n this.skippable = options.skippable;\n\n this.selector = new AppSelectPeers({\n appendTo: this.content, \n onChange: this.skippable ? null : (length) => {\n this.nextBtn.classList.toggle('is-visible', !!length);\n }, \n peerType: ['contacts'],\n placeholder: options.placeholder\n });\n\n if(options.selectedPeerIds) {\n this.selector.addInitial(options.selectedPeerIds);\n }\n\n this.nextBtn.classList.add('tgico-arrow_next');\n this.nextBtn.innerHTML = '';\n this.nextBtn.disabled = false;\n this.nextBtn.classList.toggle('is-visible', this.skippable);\n\n return ret;\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport appMessagesManager, { AppMessagesManager } from \"../../../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../../../lib/appManagers/appPeersManager\";\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport appUsersManager, { User } from \"../../../lib/appManagers/appUsersManager\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport rootScope from \"../../../lib/rootScope\";\nimport AppSearchSuper, { SearchSuperType } from \"../../appSearchSuper.\";\nimport AvatarElement, { openAvatarViewer } from \"../../avatar\";\nimport SidebarSlider, { SliderSuperTab } from \"../../slider\";\nimport CheckboxField from \"../../checkboxField\";\nimport { attachClickEvent, replaceContent, cancelEvent } from \"../../../helpers/dom\";\nimport appSidebarRight from \"..\";\nimport { TransitionSlider } from \"../../transition\";\nimport appNotificationsManager from \"../../../lib/appManagers/appNotificationsManager\";\nimport AppEditGroupTab from \"./editGroup\";\nimport PeerTitle from \"../../peerTitle\";\nimport AppEditChannelTab from \"./editChannel\";\nimport AppEditContactTab from \"./editContact\";\nimport appChatsManager, { Channel } from \"../../../lib/appManagers/appChatsManager\";\nimport { Chat, Message, MessageAction, ChatFull, Photo } from \"../../../layer\";\nimport Button from \"../../button\";\nimport ButtonIcon from \"../../buttonIcon\";\nimport I18n, { i18n, LangPackKey } from \"../../../lib/langPack\";\nimport { SettingSection } from \"../../sidebarLeft\";\nimport Row from \"../../row\";\nimport { copyTextToClipboard } from \"../../../helpers/clipboard\";\nimport { toast } from \"../../toast\";\nimport { fastRaf } from \"../../../helpers/schedulers\";\nimport { safeAssign } from \"../../../helpers/object\";\nimport { forEachReverse } from \"../../../helpers/array\";\nimport appPhotosManager from \"../../../lib/appManagers/appPhotosManager\";\nimport renderImageFromUrl from \"../../../helpers/dom/renderImageFromUrl\";\nimport SwipeHandler from \"../../swipeHandler\";\nimport { MOUNT_CLASS_TO } from \"../../../config/debug\";\nimport AppAddMembersTab from \"../../sidebarLeft/tabs/addMembers\";\nimport PopupPickUser from \"../../popups/pickUser\";\nimport PopupPeer from \"../../popups/peer\";\nimport Scrollable from \"../../scrollable\";\nimport { isTouchSupported } from \"../../../helpers/touchSupport\";\nimport { isFirefox } from \"../../../helpers/userAgent\";\n\nlet setText = (text: string, row: Row) => {\n //fastRaf(() => {\n row.title.innerHTML = text;\n row.container.style.display = '';\n //});\n};\n\nconst PARALLAX_SUPPORTED = !isFirefox;\n\ntype ListLoaderResult<T> = {count: number, items: any[]};\nclass ListLoader<T> {\n public current: T;\n public previous: T[] = [];\n public next: T[] = [];\n public count: number;\n\n public tempId = 0;\n public loadMore: (anchor: T, older: boolean) => Promise<ListLoaderResult<T>>;\n public processItem: (item: any) => false | T;\n public onJump: (item: T, older: boolean) => void;\n public loadCount = 50;\n public reverse = false; // reverse means next = higher msgid\n\n public loadedAllUp = false;\n public loadedAllDown = false;\n public loadPromiseUp: Promise<void>;\n public loadPromiseDown: Promise<void>;\n\n constructor(options: {\n loadMore: ListLoader<T>['loadMore'],\n loadCount: ListLoader<T>['loadCount'],\n processItem?: ListLoader<T>['processItem'],\n onJump: ListLoader<T>['onJump'],\n }) {\n safeAssign(this, options);\n\n\n }\n\n get index() {\n return this.count !== undefined ? this.previous.length : -1;\n }\n\n public go(length: number) {\n let items: T[], item: T;\n if(length > 0) {\n items = this.next.splice(0, length);\n item = items.pop();\n if(!item) {\n return;\n }\n\n this.previous.push(this.current, ...items);\n } else {\n items = this.previous.splice(this.previous.length + length, -length);\n item = items.shift();\n if(!item) {\n return;\n }\n\n this.next.unshift(...items, this.current);\n }\n\n this.current = item;\n this.onJump(item, length > 0);\n }\n\n public load(older: boolean) {\n if(older && this.loadedAllDown) return Promise.resolve();\n else if(!older && this.loadedAllUp) return Promise.resolve();\n\n if(older && this.loadPromiseDown) return this.loadPromiseDown;\n else if(!older && this.loadPromiseUp) return this.loadPromiseUp;\n\n /* const loadCount = 50;\n const backLimit = older ? 0 : loadCount; */\n \n let anchor: T;\n if(older) {\n anchor = this.reverse ? this.previous[0] : this.next[this.next.length - 1];\n } else {\n anchor = this.reverse ? this.next[this.next.length - 1] : this.previous[0];\n }\n\n const promise = this.loadMore(anchor, older).then(result => {\n if(result.items.length < this.loadCount) {\n if(older) this.loadedAllDown = true;\n else this.loadedAllUp = true;\n }\n\n if(this.count === undefined) {\n this.count = result.count || result.items.length;\n }\n\n const method = older ? result.items.forEach.bind(result.items) : forEachReverse.bind(null, result.items);\n method((item: any) => {\n const processed = this.processItem ? this.processItem(item) : item;\n\n if(!processed) return;\n\n if(older) {\n if(this.reverse) this.previous.unshift(processed);\n else this.next.push(processed);\n } else {\n if(this.reverse) this.next.push(processed);\n else this.previous.unshift(processed);\n }\n });\n }, () => {}).then(() => {\n if(older) this.loadPromiseDown = null;\n else this.loadPromiseUp = null;\n });\n\n if(older) this.loadPromiseDown = promise;\n else this.loadPromiseUp = promise;\n\n return promise;\n }\n}\n\nclass PeerProfileAvatars {\n private static BASE_CLASS = 'profile-avatars';\n private static SCALE = PARALLAX_SUPPORTED ? 2 : 1;\n private static TRANSLATE_TEMPLATE = PARALLAX_SUPPORTED ? `translate3d({x}, 0, -1px) scale(${PeerProfileAvatars.SCALE})` : 'translate({x}, 0)';\n public container: HTMLElement;\n public avatars: HTMLElement;\n public gradient: HTMLElement;\n public info: HTMLElement;\n private tabs: HTMLDivElement;\n private listLoader: ListLoader<string | Message.messageService>;\n private peerId: number;\n\n constructor(public scrollable: Scrollable) {\n this.container = document.createElement('div');\n this.container.classList.add(PeerProfileAvatars.BASE_CLASS + '-container');\n\n this.avatars = document.createElement('div');\n this.avatars.classList.add(PeerProfileAvatars.BASE_CLASS + '-avatars');\n\n this.gradient = document.createElement('div');\n this.gradient.classList.add(PeerProfileAvatars.BASE_CLASS + '-gradient');\n\n this.info = document.createElement('div');\n this.info.classList.add(PeerProfileAvatars.BASE_CLASS + '-info');\n\n this.tabs = document.createElement('div');\n this.tabs.classList.add(PeerProfileAvatars.BASE_CLASS + '-tabs');\n\n this.container.append(this.avatars, this.gradient, this.info, this.tabs);\n\n const checkScrollTop = () => {\n if(this.scrollable.scrollTop !== 0) {\n this.scrollable.scrollIntoViewNew(this.scrollable.container.firstElementChild as HTMLElement, 'start');\n return false;\n }\n\n return true;\n };\n\n const SWITCH_ZONE = 1 / 3;\n let cancel = false;\n let freeze = false;\n attachClickEvent(this.container, async(_e) => {\n if(freeze) {\n cancelEvent(_e);\n return;\n }\n\n if(cancel) {\n cancel = false;\n return;\n }\n\n if(!checkScrollTop()) {\n return;\n }\n\n const rect = this.container.getBoundingClientRect();\n\n const e = (_e as TouchEvent).touches ? (_e as TouchEvent).touches[0] : _e as MouseEvent;\n const x = e.pageX;\n\n const clickX = x - rect.left;\n if((!this.listLoader.previous.length && !this.listLoader.next.length) \n || (clickX > (rect.width * SWITCH_ZONE) && clickX < (rect.width - rect.width * SWITCH_ZONE))) {\n const peerId = this.peerId;\n\n const targets: {element: HTMLElement, item: string | Message.messageService}[] = [];\n this.listLoader.previous.concat(this.listLoader.current, this.listLoader.next).forEach((item, idx) => {\n targets.push({\n element: /* null */this.avatars.children[idx] as HTMLElement,\n item\n });\n });\n\n const prevTargets = targets.slice(0, this.listLoader.previous.length);\n const nextTargets = targets.slice(this.listLoader.previous.length + 1);\n\n const target = this.avatars.children[this.listLoader.previous.length] as HTMLElement;\n freeze = true;\n openAvatarViewer(target, peerId, () => peerId === this.peerId, this.listLoader.current, prevTargets, nextTargets);\n freeze = false;\n } else {\n const centerX = rect.right - (rect.width / 2);\n const toRight = x > centerX;\n \n // this.avatars.classList.remove('no-transition');\n // fastRaf(() => {\n this.listLoader.go(toRight ? 1 : -1);\n // });\n }\n });\n\n const cancelNextClick = () => {\n cancel = true;\n document.body.addEventListener(isTouchSupported ? 'touchend' : 'click', (e) => {\n cancel = false;\n }, {once: true});\n };\n\n let width = 0, x = 0, lastDiffX = 0, lastIndex = 0, minX = 0;\n const swipeHandler = new SwipeHandler({\n element: this.avatars, \n onSwipe: (xDiff, yDiff) => {\n lastDiffX = xDiff;\n let lastX = x + xDiff * -PeerProfileAvatars.SCALE;\n if(lastX > 0) lastX = 0;\n else if(lastX < minX) lastX = minX;\n\n this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', lastX + 'px');\n //console.log(xDiff, yDiff);\n return false;\n }, \n verifyTouchTarget: (e) => {\n if(!checkScrollTop()) {\n cancelNextClick();\n cancelEvent(e);\n return false;\n } else if(this.tabs.classList.contains('hide') || freeze) {\n return false;\n }\n\n return true;\n }, \n onFirstSwipe: () => {\n const rect = this.avatars.getBoundingClientRect();\n width = rect.width;\n minX = -width * (this.tabs.childElementCount - 1);\n\n /* lastIndex = whichChild(this.tabs.querySelector('.active'));\n x = -width * lastIndex; */\n x = rect.left - this.container.getBoundingClientRect().left;\n \n this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', x + 'px');\n\n this.avatars.classList.add('no-transition');\n void this.avatars.offsetLeft; // reflow\n },\n onReset: () => {\n const addIndex = Math.ceil(Math.abs(lastDiffX) / (width / PeerProfileAvatars.SCALE)) * (lastDiffX >= 0 ? 1 : -1);\n cancelNextClick();\n \n //console.log(addIndex);\n\n this.avatars.classList.remove('no-transition');\n fastRaf(() => {\n this.listLoader.go(addIndex);\n });\n }\n });\n }\n\n public setPeer(peerId: number) {\n this.peerId = peerId;\n\n const photo = appPeersManager.getPeerPhoto(peerId);\n if(!photo) {\n return;\n }\n\n const loadCount = 50;\n const listLoader: PeerProfileAvatars['listLoader'] = this.listLoader = new ListLoader<string | Message.messageService>({\n loadCount,\n loadMore: (anchor, older) => {\n if(peerId > 0) {\n return appPhotosManager.getUserPhotos(peerId, (anchor || listLoader.current) as any, loadCount).then(result => {\n return {\n count: result.count,\n items: result.photos\n };\n });\n } else {\n const promises: [Promise<ChatFull>, ReturnType<AppMessagesManager['getSearch']>] = [] as any;\n if(!listLoader.current) {\n promises.push(appProfileManager.getChatFull(-peerId));\n }\n \n promises.push(appMessagesManager.getSearch({\n peerId,\n maxId: Number.MAX_SAFE_INTEGER,\n inputFilter: {\n _: 'inputMessagesFilterChatPhotos'\n },\n limit: loadCount,\n backLimit: 0\n }));\n\n return Promise.all(promises).then((result) => {\n const value = result.pop() as typeof result[1];\n\n if(!listLoader.current) {\n const chatFull = result[0];\n const message = value.history.findAndSplice(m => {\n return ((m as Message.messageService).action as MessageAction.messageActionChannelEditPhoto).photo.id === chatFull.chat_photo.id;\n }) as Message.messageService;\n \n listLoader.current = message || appMessagesManager.generateFakeAvatarMessage(this.peerId, chatFull.chat_photo);\n }\n\n //console.log('avatars loaded:', value);\n return {\n count: value.count,\n items: value.history\n };\n });\n }\n },\n processItem: this.processItem,\n onJump: (item, older) => {\n const id = this.listLoader.index;\n //const nextId = Math.max(0, id);\n const x = 100 * PeerProfileAvatars.SCALE * id;\n this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', `-${x}%`);\n\n const activeTab = this.tabs.querySelector('.active');\n if(activeTab) activeTab.classList.remove('active');\n\n const tab = this.tabs.children[id] as HTMLElement;\n tab.classList.add('active');\n }\n });\n\n if(photo._ === 'userProfilePhoto') {\n listLoader.current = photo.photo_id;\n }\n\n this.processItem(listLoader.current);\n\n listLoader.load(true);\n }\n\n public addTab() {\n const tab = document.createElement('div');\n tab.classList.add(PeerProfileAvatars.BASE_CLASS + '-tab');\n this.tabs.append(tab);\n\n if(this.tabs.childElementCount === 1) {\n tab.classList.add('active');\n }\n\n this.tabs.classList.toggle('hide', this.tabs.childElementCount <= 1);\n }\n\n public processItem = (photoId: string | Message.messageService) => {\n const avatar = document.createElement('div');\n avatar.classList.add(PeerProfileAvatars.BASE_CLASS + '-avatar');\n\n let photo: Photo.photo;\n if(photoId) {\n photo = typeof(photoId) === 'string' ? \n appPhotosManager.getPhoto(photoId) : \n (photoId.action as MessageAction.messageActionChannelEditPhoto).photo as Photo.photo;\n }\n\n const img = new Image();\n img.classList.add(PeerProfileAvatars.BASE_CLASS + '-avatar-image');\n img.draggable = false;\n\n if(photo) {\n appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 420, 420, false)).then(() => {\n renderImageFromUrl(img, photo.url, () => {\n avatar.append(img);\n });\n });\n } else {\n const photo = appPeersManager.getPeerPhoto(this.peerId);\n appProfileManager.putAvatar(avatar, this.peerId, photo, 'photo_big', img);\n }\n\n this.avatars.append(avatar);\n\n this.addTab();\n\n return photoId;\n };\n}\n\nclass PeerProfile {\n public element: HTMLElement;\n public avatars: PeerProfileAvatars;\n private avatar: AvatarElement;\n private section: SettingSection;\n private name: HTMLDivElement;\n private subtitle: HTMLDivElement;\n private bio: Row;\n private username: Row;\n private phone: Row;\n private notifications: Row;\n \n private cleaned: boolean;\n private setBioTimeout: number;\n private setPeerStatusInterval: number;\n\n private peerId = 0;\n private threadId: number;\n\n constructor(public scrollable: Scrollable) {\n if(!PARALLAX_SUPPORTED) {\n this.scrollable.container.classList.add('no-parallax');\n }\n }\n\n public init() {\n this.init = null;\n\n this.element = document.createElement('div');\n this.element.classList.add('profile-content');\n\n this.section = new SettingSection({\n noDelimiter: true\n });\n\n this.avatar = new AvatarElement();\n this.avatar.classList.add('profile-avatar', 'avatar-120');\n this.avatar.setAttribute('dialog', '1');\n this.avatar.setAttribute('clickable', '');\n\n this.name = document.createElement('div');\n this.name.classList.add('profile-name');\n\n this.subtitle = document.createElement('div');\n this.subtitle.classList.add('profile-subtitle');\n\n this.bio = new Row({\n title: ' ',\n subtitleLangKey: 'UserBio',\n icon: 'info',\n clickable: (e) => {\n if((e.target as HTMLElement).tagName === 'A') {\n return;\n }\n \n appProfileManager.getProfileByPeerId(this.peerId).then(full => {\n copyTextToClipboard(full.about);\n toast(I18n.format('BioCopied', true));\n });\n }\n });\n\n this.bio.title.classList.add('pre-wrap');\n\n this.username = new Row({\n title: ' ',\n subtitleLangKey: 'Username',\n icon: 'username',\n clickable: () => {\n const peer: Channel | User = appPeersManager.getPeer(this.peerId);\n copyTextToClipboard('@' + peer.username);\n toast(I18n.format('UsernameCopied', true));\n }\n });\n\n this.phone = new Row({\n title: ' ',\n subtitleLangKey: 'Phone',\n icon: 'phone',\n clickable: () => {\n const peer: User = appUsersManager.getUser(this.peerId);\n copyTextToClipboard('+' + peer.phone);\n toast(I18n.format('PhoneCopied', true));\n }\n });\n\n this.notifications = new Row({\n checkboxField: new CheckboxField({toggle: true}),\n titleLangKey: 'Notifications',\n icon: 'unmute'\n });\n \n this.section.content.append(this.phone.container, this.username.container, this.bio.container, this.notifications.container);\n\n const delimiter = document.createElement('div');\n delimiter.classList.add('gradient-delimiter');\n\n this.element.append(this.section.container, delimiter);\n\n this.notifications.checkboxField.input.addEventListener('change', (e) => {\n if(!e.isTrusted) {\n return;\n }\n\n //let checked = this.notificationsCheckbox.checked;\n appMessagesManager.mutePeer(this.peerId);\n });\n\n rootScope.on('dialog_notify_settings', (dialog) => {\n if(this.peerId === dialog.peerId) {\n const muted = appNotificationsManager.isPeerLocalMuted(this.peerId, false);\n this.notifications.checkboxField.checked = !muted;\n }\n });\n\n rootScope.on('peer_typings', (e) => {\n const {peerId} = e;\n\n if(this.peerId === peerId) {\n this.setPeerStatus();\n }\n });\n\n rootScope.on('peer_bio_edit', (peerId) => {\n if(peerId === this.peerId) {\n this.setBio(true);\n }\n });\n\n rootScope.on('user_update', (e) => {\n const userId = e;\n\n if(this.peerId === userId) {\n this.setPeerStatus();\n }\n });\n\n this.setPeerStatusInterval = window.setInterval(this.setPeerStatus, 60e3);\n }\n\n public setPeerStatus = (needClear = false) => {\n if(!this.peerId) return;\n\n const peerId = this.peerId;\n appImManager.setPeerStatus(this.peerId, this.subtitle, needClear, true, () => peerId === this.peerId);\n };\n\n public cleanupHTML() {\n this.bio.container.style.display = 'none';\n this.phone.container.style.display = 'none';\n this.username.container.style.display = 'none';\n this.notifications.container.style.display = '';\n this.notifications.checkboxField.checked = true;\n if(this.setBioTimeout) {\n window.clearTimeout(this.setBioTimeout);\n this.setBioTimeout = 0;\n }\n }\n\n public setAvatar() {\n if(this.peerId !== rootScope.myId) {\n const photo = appPeersManager.getPeerPhoto(this.peerId);\n\n if(photo) {\n const oldAvatars = this.avatars;\n this.avatars = new PeerProfileAvatars(this.scrollable);\n this.avatars.setPeer(this.peerId);\n this.avatars.info.append(this.name, this.subtitle);\n \n this.avatar.remove();\n \n if(oldAvatars) oldAvatars.container.replaceWith(this.avatars.container);\n else this.element.prepend(this.avatars.container);\n\n if(PARALLAX_SUPPORTED) {\n this.scrollable.container.classList.add('parallax');\n }\n\n return;\n }\n }\n\n if(PARALLAX_SUPPORTED) {\n this.scrollable.container.classList.remove('parallax');\n }\n\n if(this.avatars) {\n this.avatars.container.remove();\n this.avatars = undefined;\n }\n\n this.avatar.setAttribute('peer', '' + this.peerId);\n\n this.section.content.prepend(this.avatar, this.name, this.subtitle);\n }\n\n public fillProfileElements() {\n if(!this.cleaned) return;\n this.cleaned = false;\n \n const peerId = this.peerId;\n\n this.cleanupHTML();\n\n this.setAvatar();\n\n // username\n if(peerId !== rootScope.myId) {\n let username = appPeersManager.getPeerUsername(peerId);\n if(username) {\n setText(appPeersManager.getPeerUsername(peerId), this.username);\n }\n \n const muted = appNotificationsManager.isPeerLocalMuted(peerId, false);\n this.notifications.checkboxField.checked = !muted;\n } else {\n window.requestAnimationFrame(() => {\n this.notifications.container.style.display = 'none';\n });\n }\n \n //let membersLi = this.profileTabs.firstElementChild.children[0] as HTMLLIElement;\n if(peerId > 0) {\n //membersLi.style.display = 'none';\n\n let user = appUsersManager.getUser(peerId);\n if(user.phone && peerId !== rootScope.myId) {\n setText(user.rPhone, this.phone);\n }\n }/* else {\n //membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : '';\n } */\n\n this.setBio();\n\n replaceContent(this.name, new PeerTitle({\n peerId,\n dialog: true\n }).element);\n\n this.setPeerStatus(true);\n }\n\n public setBio(override?: true) {\n if(this.setBioTimeout) {\n window.clearTimeout(this.setBioTimeout);\n this.setBioTimeout = 0;\n }\n\n const peerId = this.peerId;\n const threadId = this.threadId;\n\n if(!peerId) {\n return;\n }\n\n let promise: Promise<boolean>;\n if(peerId > 0) {\n promise = appProfileManager.getProfile(peerId, override).then(userFull => {\n if(this.peerId !== peerId || this.threadId !== threadId) {\n //this.log.warn('peer changed');\n return false;\n }\n \n if(userFull.rAbout && peerId !== rootScope.myId) {\n setText(userFull.rAbout, this.bio);\n }\n \n //this.log('userFull', userFull);\n return true;\n });\n } else {\n promise = appProfileManager.getChatFull(-peerId, override).then((chatFull) => {\n if(this.peerId !== peerId || this.threadId !== threadId) {\n //this.log.warn('peer changed');\n return false;\n }\n \n //this.log('chatInfo res 2:', chatFull);\n \n if(chatFull.about) {\n setText(RichTextProcessor.wrapRichText(chatFull.about), this.bio);\n }\n\n return true;\n });\n }\n\n promise.then((canSetNext) => {\n if(canSetNext) {\n this.setBioTimeout = window.setTimeout(() => this.setBio(true), 60e3);\n }\n });\n }\n\n public setPeer(peerId: number, threadId = 0) {\n if(this.peerId === peerId && this.threadId === peerId) return;\n\n if(this.init) {\n this.init();\n }\n\n this.peerId = peerId;\n this.threadId = threadId;\n \n this.cleaned = true;\n }\n}\n\n// TODO: отредактированное сообщение не изменится\nexport default class AppSharedMediaTab extends SliderSuperTab {\n private editBtn: HTMLElement;\n\n private peerId = 0;\n private threadId = 0;\n\n private historiesStorage: {\n [peerId: number]: Partial<{\n [type in SearchSuperType]: {mid: number, peerId: number}[]\n }>\n } = {};\n\n private searchSuper: AppSearchSuper;\n\n private profile: PeerProfile;\n peerChanged: boolean;\n\n constructor(slider: SidebarSlider) {\n super(slider, false);\n }\n\n public init() {\n //const perf = performance.now();\n\n this.container.classList.add('shared-media-container', 'profile-container');\n\n // * header\n const newCloseBtn = Button('btn-icon sidebar-close-button', {noRipple: true});\n this.closeBtn.replaceWith(newCloseBtn);\n this.closeBtn = newCloseBtn;\n\n const animatedCloseIcon = document.createElement('div');\n animatedCloseIcon.classList.add('animated-close-icon');\n newCloseBtn.append(animatedCloseIcon);\n\n const transitionContainer = document.createElement('div');\n transitionContainer.className = 'transition slide-fade';\n \n const transitionFirstItem = document.createElement('div');\n transitionFirstItem.classList.add('transition-item');\n\n this.title.append(i18n('Profile'));\n this.editBtn = ButtonIcon('edit');\n //const moreBtn = ButtonIcon('more');\n\n transitionFirstItem.append(this.title, this.editBtn/* , moreBtn */);\n\n const transitionLastItem = document.createElement('div');\n transitionLastItem.classList.add('transition-item');\n\n const secondTitle: HTMLElement = this.title.cloneNode() as any;\n secondTitle.append(i18n('PeerInfo.SharedMedia'));\n\n transitionLastItem.append(secondTitle);\n\n transitionContainer.append(transitionFirstItem, transitionLastItem);\n\n this.header.append(transitionContainer);\n\n // * body\n\n this.profile = new PeerProfile(this.scrollable);\n this.profile.init();\n \n this.scrollable.append(this.profile.element);\n\n const HEADER_HEIGHT = 56;\n this.scrollable.onAdditionalScroll = () => {\n const rect = this.searchSuper.nav.getBoundingClientRect(); \n if(!rect.width) return;\n\n const top = rect.top;\n const isSharedMedia = top <= HEADER_HEIGHT;\n animatedCloseIcon.classList.toggle('state-back', isSharedMedia);\n this.searchSuper.container.classList.toggle('is-full-viewport', isSharedMedia);\n transition(+isSharedMedia);\n\n if(!isSharedMedia) {\n this.searchSuper.cleanScrollPositions();\n }\n };\n\n const transition = TransitionSlider(transitionContainer, 'slide-fade', 400, null, false);\n\n transition(0);\n\n attachClickEvent(this.closeBtn, (e) => {\n if(this.closeBtn.firstElementChild.classList.contains('state-back')) {\n this.scrollable.scrollIntoViewNew(this.scrollable.container.firstElementChild as HTMLElement, 'start');\n transition(0);\n animatedCloseIcon.classList.remove('state-back');\n } else if(!this.scrollable.isHeavyAnimationInProgress) {\n appSidebarRight.onCloseBtnClick();\n }\n });\n\n attachClickEvent(this.editBtn, (e) => {\n let tab: AppEditGroupTab | AppEditChannelTab | AppEditContactTab;\n if(appPeersManager.isAnyGroup(this.peerId)) {\n tab = new AppEditGroupTab(appSidebarRight);\n } else if(this.peerId > 0) {\n tab = new AppEditContactTab(appSidebarRight);\n } else {\n tab = new AppEditChannelTab(appSidebarRight);\n }\n\n if(tab) {\n if(tab instanceof AppEditGroupTab) {\n tab.chatId = -this.peerId;\n } else {\n tab.peerId = this.peerId;\n }\n \n tab.open();\n }\n });\n\n //this.container.prepend(this.closeBtn.parentElement);\n\n this.searchSuper = new AppSearchSuper({\n mediaTabs: [{\n inputFilter: 'inputMessagesFilterEmpty',\n name: 'PeerMedia.Members',\n type: 'members'\n }, {\n inputFilter: 'inputMessagesFilterPhotoVideo',\n name: 'SharedMediaTab2',\n type: 'media'\n }, {\n inputFilter: 'inputMessagesFilterDocument',\n name: 'SharedFilesTab2',\n type: 'files'\n }, {\n inputFilter: 'inputMessagesFilterUrl',\n name: 'SharedLinksTab2',\n type: 'links'\n }, {\n inputFilter: 'inputMessagesFilterMusic',\n name: 'SharedMusicTab2',\n type: 'music'\n }, {\n inputFilter: 'inputMessagesFilterVoice',\n name: 'SharedVoiceTab2',\n type: 'voice'\n }], \n scrollable: this.scrollable,\n onChangeTab: (mediaTab) => {\n let timeout = mediaTab.type === 'members' && rootScope.settings.animationsEnabled ? 250 : 0;\n setTimeout(() => {\n btnAddMembers.classList.toggle('is-hidden', mediaTab.type !== 'members');\n }, timeout);\n }\n });\n\n this.profile.element.append(this.searchSuper.container);\n\n const btnAddMembers = Button('btn-corner btn-circle', {icon: 'addmember_filled'});\n this.content.append(btnAddMembers);\n\n btnAddMembers.addEventListener('click', () => {\n const id = -this.peerId;\n const isChannel = appChatsManager.isChannel(id);\n\n const showConfirmation = (peerIds: number[], callback: () => void) => {\n let titleLangKey: LangPackKey = 'GroupAddMembers', descriptionLangKey: LangPackKey, descriptionLangArgs: any[];\n\n if(peerIds.length > 1) {\n descriptionLangKey = 'PeerInfo.Confirm.AddMembers1';\n descriptionLangArgs = [peerIds.length];\n } else {\n descriptionLangKey = 'PeerInfo.Confirm.AddMember';\n descriptionLangArgs = [new PeerTitle({\n peerId: peerIds[0],\n onlyFirstName: true\n }).element];\n }\n\n new PopupPeer('popup-add-members', {\n peerId: -id,\n titleLangKey,\n descriptionLangKey,\n descriptionLangArgs,\n buttons: [{\n langKey: 'Add',\n callback: () => {\n callback();\n }\n }]\n }).show();\n };\n \n if(isChannel) {\n const tab = new AppAddMembersTab(this.slider);\n tab.open({\n peerId: this.peerId,\n type: 'channel',\n skippable: false,\n takeOut: (peerIds) => {\n showConfirmation(peerIds, () => {\n tab.attachToPromise(appChatsManager.inviteToChannel(id, peerIds));\n });\n\n return false;\n },\n title: 'GroupAddMembers',\n placeholder: 'SendMessageTo'\n });\n } else {\n new PopupPickUser({\n peerTypes: ['contacts'],\n placeholder: 'Search',\n onSelect: (peerId) => {\n setTimeout(() => {\n showConfirmation([peerId], () => {\n appChatsManager.addChatUser(id, peerId);\n });\n }, 0);\n },\n });\n }\n });\n\n //console.log('construct shared media time:', performance.now() - perf);\n }\n\n public renderNewMessages(peerId: number, mids: number[]) {\n if(this.init) return; // * not inited yet\n\n if(!this.historiesStorage[peerId]) return;\n \n mids = mids.slice().reverse(); // ! because it will be ascend sorted array\n for(const mediaTab of this.searchSuper.mediaTabs) {\n const inputFilter = mediaTab.inputFilter;\n const filtered = this.searchSuper.filterMessagesByType(mids.map(mid => appMessagesManager.getMessageByPeer(peerId, mid)), inputFilter);\n if(filtered.length) {\n if(this.historiesStorage[peerId][inputFilter]) {\n this.historiesStorage[peerId][inputFilter].unshift(...filtered.map(message => ({mid: message.mid, peerId: message.peerId})));\n }\n\n if(this.peerId === peerId && this.searchSuper.usedFromHistory[inputFilter] !== -1) {\n this.searchSuper.usedFromHistory[inputFilter] += filtered.length;\n this.searchSuper.performSearchResult(filtered, mediaTab, false);\n }\n\n break;\n }\n }\n }\n\n public deleteDeletedMessages(peerId: number, mids: number[]) {\n if(this.init) return; // * not inited yet\n\n if(!this.historiesStorage[peerId]) return;\n\n for(const mid of mids) {\n for(const type of this.searchSuper.mediaTabs) {\n const inputFilter = type.inputFilter;\n\n if(!this.historiesStorage[peerId][inputFilter]) continue;\n\n const history = this.historiesStorage[peerId][inputFilter];\n const idx = history.findIndex(m => m.mid === mid);\n if(idx !== -1) {\n history.splice(idx, 1);\n\n if(this.peerId === peerId) {\n const container = this.searchSuper.tabs[inputFilter];\n const div = container.querySelector(`div[data-mid=\"${mid}\"][data-peer-id=\"${peerId}\"]`);\n if(div) {\n div.remove();\n }\n \n if(this.searchSuper.usedFromHistory[inputFilter] >= (idx + 1)) {\n this.searchSuper.usedFromHistory[inputFilter]--;\n }\n }\n\n break;\n }\n }\n }\n\n this.scrollable.onScroll();\n }\n\n public cleanupHTML() {\n // const perf = performance.now();\n this.profile.cleanupHTML();\n \n this.editBtn.style.display = 'none';\n\n this.searchSuper.cleanupHTML(true);\n\n this.container.classList.toggle('can-add-members', this.searchSuper.canViewMembers() && appChatsManager.hasRights(-this.peerId, 'invite_users'));\n\n // console.log('cleanupHTML shared media time:', performance.now() - perf);\n }\n\n public setLoadMutex(promise: Promise<any>) {\n this.searchSuper.loadMutex = promise;\n }\n\n public setPeer(peerId: number, threadId = 0) {\n if(this.peerId === peerId && this.threadId === threadId) return false;\n\n this.peerId = peerId;\n this.threadId = threadId;\n this.peerChanged = true;\n\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n this.searchSuper.setQuery({\n peerId, \n //threadId, \n historyStorage: this.historiesStorage[peerId] ?? (this.historiesStorage[peerId] = {})\n });\n\n this.profile.setPeer(peerId, threadId);\n \n return true;\n }\n\n public fillProfileElements() {\n if(!this.peerChanged) {\n return;\n }\n\n this.peerChanged = false;\n\n this.cleanupHTML();\n\n this.profile.fillProfileElements();\n\n if(this.peerId > 0) {\n if(this.peerId !== rootScope.myId && appUsersManager.isContact(this.peerId)) {\n this.editBtn.style.display = '';\n }\n } else {\n const chat: Chat = appChatsManager.getChat(-this.peerId);\n if(chat._ === 'chat' || (chat as Chat.channel).admin_rights) {\n this.editBtn.style.display = '';\n }\n }\n }\n\n public loadSidebarMedia(single: boolean, justLoad = false) {\n this.searchSuper.load(single, justLoad);\n }\n\n onOpenAfterTimeout() {\n this.scrollable.onScroll();\n }\n}\n\nMOUNT_CLASS_TO && (MOUNT_CLASS_TO.AppSharedMediaTab = AppSharedMediaTab);\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appImManager from \"../../lib/appManagers/appImManager\";\nimport SidebarSlider from \"../slider\";\nimport mediaSizes, { ScreenSize } from \"../../helpers/mediaSizes\";\nimport AppSharedMediaTab from \"./tabs/sharedMedia\";\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\n\nexport const RIGHT_COLUMN_ACTIVE_CLASSNAME = 'is-right-column-shown';\n\nexport class AppSidebarRight extends SidebarSlider {\n public sharedMediaTab: AppSharedMediaTab;\n\n constructor() {\n super({\n sidebarEl: document.getElementById('column-right') as HTMLElement,\n canHideFirst: true,\n navigationType: 'right'\n });\n\n mediaSizes.addEventListener('changeScreen', (from, to) => {\n if(to === ScreenSize.medium && from !== ScreenSize.mobile) {\n this.toggleSidebar(false);\n }\n });\n\n this.sharedMediaTab = new AppSharedMediaTab(this);\n }\n\n public onCloseTab(id: number, animate: boolean, isNavigation?: boolean) {\n if(!this.historyTabIds.length) {\n this.toggleSidebar(false, animate);\n }\n\n super.onCloseTab(id, animate, isNavigation);\n }\n\n /* public selectTab(id: number) {\n const res = super.selectTab(id);\n\n if(id !== -1) {\n this.toggleSidebar(true);\n }\n\n return res;\n } */\n\n public toggleSidebar(enable?: boolean, animate?: boolean) {\n /////this.log('sidebarEl', this.sidebarEl, enable, isElementInViewport(this.sidebarEl));\n\n const active = document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME);\n let willChange: boolean;\n if(enable !== undefined) {\n if(enable) {\n if(!active) {\n willChange = true;\n }\n } else if(active) {\n willChange = true;\n }\n } else {\n willChange = true;\n }\n\n if(!willChange) return Promise.resolve();\n\n if(!active && !this.historyTabIds.length) {\n this.sharedMediaTab.open();\n //this.selectTab(this.sharedMediaTab);\n }\n\n const animationPromise = appImManager.selectTab(active ? 1 : 2, animate);\n document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, enable);\n return animationPromise;\n\n /* return new Promise((resolve, reject) => {\n const hidden: {element: HTMLDivElement, height: number}[] = [];\n const observer = new IntersectionObserver((entries) => {\n for(const entry of entries) {\n const bubble = entry.target as HTMLDivElement;\n if(!entry.isIntersecting) {\n hidden.push({element: bubble, height: bubble.scrollHeight});\n }\n }\n \n for(const item of hidden) {\n item.element.style.minHeight = item.height + 'px';\n (item.element.firstElementChild as HTMLElement).style.display = 'none';\n item.element.style.width = '1px';\n }\n \n //console.log('hidden', hidden);\n observer.disconnect();\n \n set();\n \n setTimeout(() => {\n for(const item of hidden) {\n item.element.style.minHeight = '';\n item.element.style.width = '';\n (item.element.firstElementChild as HTMLElement).style.display = '';\n }\n\n resolve();\n }, 200);\n });\n \n const length = Object.keys(appImManager.bubbles).length;\n if(length) {\n for(const i in appImManager.bubbles) {\n observer.observe(appImManager.bubbles[i]);\n }\n } else {\n set();\n setTimeout(resolve, 200);\n }\n }); */\n }\n}\n\nconst appSidebarRight = new AppSidebarRight();\nMOUNT_CLASS_TO.appSidebarRight = appSidebarRight;\nexport default appSidebarRight;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport appSidebarRight from \"..\";\nimport appPollsManager from \"../../../lib/appManagers/appPollsManager\";\nimport { roundPercents } from \"../../poll\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport { ripple } from \"../../ripple\";\nimport { i18n } from \"../../../lib/langPack\";\n\nexport default class AppPollResultsTab extends SliderSuperTab {\n private resultsDiv: HTMLElement;\n\n protected init() {\n this.container.id = 'poll-results-container';\n this.container.classList.add('chatlist-container');\n\n this.resultsDiv = document.createElement('div');\n this.resultsDiv.classList.add('poll-results');\n this.scrollable.append(this.resultsDiv);\n }\n\n public open(message: any) {\n const ret = super.open();\n const poll = appPollsManager.getPoll(message.media.poll.id);\n\n this.setTitle(poll.poll.pFlags.quiz ? 'PollResults.Title.Quiz' : 'PollResults.Title.Poll');\n\n const title = document.createElement('h3');\n title.innerHTML = poll.poll.rQuestion;\n\n const percents = poll.results.results.map(v => v.voters / poll.results.total_voters * 100);\n roundPercents(percents);\n\n const fragment = document.createDocumentFragment();\n poll.results.results.forEach((result, idx) => {\n if(!result.voters) return;\n\n const hr = document.createElement('hr');\n\n const answer = poll.poll.answers[idx];\n\n // Head\n const answerEl = document.createElement('div');\n answerEl.classList.add('poll-results-answer');\n\n const answerTitle = document.createElement('div');\n answerTitle.innerHTML = RichTextProcessor.wrapEmojiText(answer.text);\n\n const answerPercents = document.createElement('div');\n answerPercents.innerText = Math.round(percents[idx]) + '%';\n\n answerEl.append(answerTitle, answerPercents);\n\n // Humans\n const list = appDialogsManager.createChatList();\n list.classList.add('poll-results-voters');\n\n appDialogsManager.setListClickListener(list, () => {\n appSidebarRight.onCloseBtnClick();\n }, undefined, true);\n\n list.style.minHeight = Math.min(result.voters, 4) * 50 + 'px';\n\n fragment.append(hr, answerEl, list);\n\n let offset: string, limit = 4, loading = false, left = result.voters - 4;\n const load = () => {\n if(loading) return;\n loading = true;\n\n appPollsManager.getVotes(message, answer.option, offset, limit).then(votesList => {\n votesList.votes.forEach(vote => {\n const {dom} = appDialogsManager.addDialogNew({\n dialog: vote.user_id,\n container: list,\n drawStatus: false,\n rippleEnabled: false, \n meAsSaved: false,\n avatarSize: 32\n });\n dom.lastMessageSpan.parentElement.remove();\n });\n\n if(offset) {\n left -= votesList.votes.length;\n (showMore.lastElementChild as HTMLElement).replaceWith(i18n('PollResults.LoadMore', [Math.min(20, left)]));\n }\n \n offset = votesList.next_offset;\n limit = 20;\n\n if(!left || !votesList.votes.length) {\n showMore.remove();\n }\n }).finally(() => {\n loading = false;\n });\n };\n\n load();\n\n if(left <= 0) return;\n\n const showMore = document.createElement('div');\n showMore.classList.add('poll-results-more', 'show-more', 'rp-overflow');\n showMore.addEventListener('click', load);\n ripple(showMore);\n const down = document.createElement('div');\n down.classList.add('tgico-down');\n showMore.append(down, i18n('PollResults.LoadMore', [Math.min(20, left)]));\n\n fragment.append(showMore);\n });\n\n this.resultsDiv.append(title, fragment);\n\n appSidebarRight.toggleSidebar(true).then(() => {\n /* appPollsManager.getVotes(mid).then(votes => {\n console.log('gOt VotEs', votes);\n }); */\n });\n\n return ret;\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport mediaSizes from \"../helpers/mediaSizes\";\nimport { isTouchSupported } from \"../helpers/touchSupport\";\nimport appImManager from \"../lib/appManagers/appImManager\";\nimport appPollsManager, { Poll, PollResults } from \"../lib/appManagers/appPollsManager\";\nimport serverTimeManager from \"../lib/mtproto/serverTimeManager\";\nimport { RichTextProcessor } from \"../lib/richtextprocessor\";\nimport rootScope from \"../lib/rootScope\";\nimport { attachClickEvent, cancelEvent, detachClickEvent, replaceContent } from \"../helpers/dom\";\nimport { ripple } from \"./ripple\";\nimport appSidebarRight from \"./sidebarRight\";\nimport AppPollResultsTab from \"./sidebarRight/tabs/pollResults\";\nimport { i18n, LangPackKey } from \"../lib/langPack\";\nimport { fastRaf } from \"../helpers/schedulers\";\nimport SetTransition from \"./singleTransition\";\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\n\nlet lineTotalLength = 0;\n//const tailLength = 9;\nconst times = 10;\nconst fullTime = 340;\nconst oneTime = fullTime / times;\n\nexport const roundPercents = (percents: number[]) => {\n //console.log('roundPercents before percents:', percents);\n\n const sum = percents.reduce((acc, p) => acc + Math.round(p), 0);\n if(sum > 100) {\n const diff = sum - 100;\n const length = percents.length;\n for(let i = 0; i < diff; ++i) {\n let minIndex = -1, minRemainder = 1;\n for(let k = 0; k < length; ++k) {\n let remainder = percents[k] % 1;\n if(remainder >= 0.5 && remainder < minRemainder) {\n minRemainder = remainder;\n minIndex = k;\n }\n }\n\n if(minIndex === -1) {\n //throw new Error('lol chto');\n return;\n }\n\n percents[minIndex] -= minRemainder;\n }\n } else if(sum < 100) {\n const diff = 100 - sum;\n const length = percents.length;\n for(let i = 0; i < diff; ++i) {\n let minIndex = -1, maxRemainder = 0;\n for(let k = 0; k < length; ++k) {\n let remainder = percents[k] % 1;\n if(remainder < 0.5 && remainder > maxRemainder) {\n maxRemainder = remainder;\n minIndex = k;\n }\n }\n\n if(minIndex === -1) {\n //throw new Error('lol chto');\n return;\n }\n\n percents[minIndex] += 1 - maxRemainder;\n }\n }\n\n //console.log('roundPercents after percents:', percents);\n};\n\n/* const connectedPolls: {id: string, element: PollElement}[] = [];\nrootScope.on('poll_update', (e) => {\n const {poll, results} = e as {poll: Poll, results: PollResults};\n\n //console.log('poll_update', poll, results);\n for(const connected of connectedPolls) {\n if(connected.id === poll.id) {\n const pollElement = connected.element;\n pollElement.isClosed = !!poll.pFlags.closed;\n pollElement.performResults(results, poll.chosenIndexes);\n }\n }\n}); */\n\nrootScope.on('poll_update', (e) => {\n const {poll, results} = e as {poll: Poll, results: PollResults};\n\n const pollElements = Array.from(document.querySelectorAll(`poll-element[poll-id=\"${poll.id}\"]`)) as PollElement[];\n pollElements.forEach(pollElement => {\n //console.log('poll_update', poll, results);\n pollElement.isClosed = !!poll.pFlags.closed;\n pollElement.performResults(results, poll.chosenIndexes);\n });\n});\n\nrootScope.on('peer_changed', () => {\n if(prevQuizHint) {\n hideQuizHint(prevQuizHint, prevQuizHintOnHide, prevQuizHintTimeout);\n }\n});\n\nconst hideQuizHint = (element: HTMLElement, onHide: () => void, timeout: number) => {\n element.classList.remove('active');\n\n clearTimeout(timeout);\n setTimeout(() => {\n onHide();\n element.remove();\n\n if(prevQuizHint === element && prevQuizHintOnHide === onHide && prevQuizHintTimeout === timeout) {\n prevQuizHint = prevQuizHintOnHide = null;\n prevQuizHintTimeout = 0;\n }\n }, 200);\n};\n\nlet prevQuizHint: HTMLElement, prevQuizHintOnHide: () => void, prevQuizHintTimeout: number;\nconst setQuizHint = (solution: string, solution_entities: any[], onHide: () => void) => {\n if(prevQuizHint) {\n hideQuizHint(prevQuizHint, prevQuizHintOnHide, prevQuizHintTimeout);\n }\n\n const element = document.createElement('div');\n element.classList.add('quiz-hint');\n\n const container = document.createElement('div');\n container.classList.add('container', 'tgico');\n\n const textEl = document.createElement('div');\n textEl.classList.add('text');\n\n container.append(textEl);\n element.append(container);\n\n textEl.innerHTML = RichTextProcessor.wrapRichText(solution, {entities: solution_entities});\n appImManager.chat.bubbles.bubblesContainer.append(element);\n\n void element.offsetLeft; // reflow\n element.classList.add('active');\n\n prevQuizHint = element;\n prevQuizHintOnHide = onHide;\n prevQuizHintTimeout = window.setTimeout(() => {\n hideQuizHint(element, onHide, prevQuizHintTimeout);\n }, isTouchSupported ? 5000 : 7000);\n};\n\nexport default class PollElement extends HTMLElement {\n private svgLines: SVGSVGElement[];\n private numberDivs: HTMLDivElement[];\n private answerDivs: HTMLDivElement[];\n private descDiv: HTMLElement;\n private typeDiv: HTMLElement;\n private avatarsDiv: HTMLElement;\n private viewResults: HTMLElement;\n private votersCountDiv: HTMLDivElement;\n\n private maxOffset = -46.5;\n //private maxLength: number;\n //private maxLengths: number[];\n private maxPercents: number[];\n\n public isClosed = false;\n private isQuiz = false;\n private isRetracted = false;\n private isPublic = false;\n private isMultiple = false;\n private chosenIndexes: number[] = [];\n private percents: number[];\n\n public message: any;\n\n private quizInterval: number;\n private quizTimer: SVGSVGElement;\n\n private sendVoteBtn: HTMLElement;\n private chosingIndexes: number[] = [];\n\n private sendVotePromise: Promise<void>;\n private sentVote = false;\n\n constructor() {\n super();\n // элемент создан\n }\n\n public render() {\n // браузер вызывает этот метод при добавлении элемента в документ\n // (может вызываться много раз, если элемент многократно добавляется/удаляется)\n\n if(!lineTotalLength) {\n lineTotalLength = (document.getElementById('poll-line') as any as SVGPathElement).getTotalLength();\n //console.log('line total length:', lineTotalLength);\n }\n\n const pollId = this.message.media.poll.id;\n const {poll, results} = appPollsManager.getPoll(pollId);\n\n /* const timestamp = Date.now() / 1000 | 0;\n if(timestamp < this.message.date) { */\n if(this.message.pFlags.is_scheduled) {\n this.classList.add('disable-hover');\n }\n\n //console.log('pollElement poll:', poll, results);\n\n let descKey: LangPackKey;\n if(poll.pFlags) {\n this.isPublic = !!poll.pFlags.public_voters;\n this.isQuiz = !!poll.pFlags.quiz;\n this.isClosed = !!poll.pFlags.closed;\n this.isMultiple = !!poll.pFlags.multiple_choice;\n\n if(this.isClosed) {\n descKey = 'Chat.Poll.Type.Closed';\n this.classList.add('is-closed');\n } else if(this.isQuiz) {\n descKey = this.isPublic ? 'Chat.Poll.Type.Quiz' : 'Chat.Poll.Type.AnonymousQuiz';\n } else {\n descKey = this.isPublic ? 'Chat.Poll.Type.Public' : 'Chat.Poll.Type.Anonymous';\n }\n }\n\n const multipleSelect = this.isMultiple ? '<span class=\"poll-answer-selected tgico-check\"></span>' : '';\n const votes = poll.answers.map((answer, idx) => {\n return `\n <div class=\"poll-answer\" data-index=\"${idx}\">\n <div class=\"circle-hover\">\n <div class=\"animation-ring\"></div>\n <svg class=\"progress-ring\">\n <circle class=\"progress-ring__circle\" cx=\"13\" cy=\"13\" r=\"9\"></circle>\n </svg>\n ${multipleSelect}\n </div>\n <div class=\"poll-answer-percents\"></div>\n <div class=\"poll-answer-text\">${RichTextProcessor.wrapEmojiText(answer.text)}</div>\n <svg version=\"1.1\" class=\"poll-line\" style=\"display: none;\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 ${mediaSizes.active.regular.width} 35\" xml:space=\"preserve\">\n <use href=\"#poll-line\"></use>\n </svg>\n <span class=\"poll-answer-selected tgico\"></span>\n </div>\n `;\n }).join('');\n\n this.innerHTML = `\n <div class=\"poll-title\">${poll.rQuestion}</div>\n <div class=\"poll-desc\">\n <div class=\"poll-type\"></div>\n <div class=\"poll-avatars\"></div>\n </div>\n ${votes}`;\n\n this.descDiv = this.firstElementChild.nextElementSibling as HTMLElement;\n this.typeDiv = this.descDiv.firstElementChild as HTMLElement;\n this.avatarsDiv = this.descDiv.lastElementChild as HTMLElement;\n\n if(descKey) {\n this.typeDiv.append(i18n(descKey));\n }\n\n if(this.isQuiz) {\n this.classList.add('is-quiz');\n\n if(poll.close_period && poll.close_date) {\n const timeLeftDiv = document.createElement('div');\n timeLeftDiv.classList.add('poll-time');\n this.descDiv.append(timeLeftDiv);\n\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n //svg.setAttributeNS(null, 'viewBox', '0 0 15 15');\n svg.classList.add('poll-quiz-timer');\n\n this.quizTimer = svg;\n\n const strokeWidth = 2;\n const radius = 7;\n const circumference = 2 * Math.PI * radius;\n\n const circle = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n circle.classList.add('poll-quiz-timer-circle');\n circle.setAttributeNS(null, 'cx', '16');\n circle.setAttributeNS(null, 'cy', '16');\n circle.setAttributeNS(null, 'r', '' + radius);\n circle.setAttributeNS(null, 'stroke-width', '' + strokeWidth);\n\n svg.append(circle);\n this.descDiv.append(svg);\n \n const period = poll.close_period * 1000;\n const closeTime = (poll.close_date - serverTimeManager.serverTimeOffset) * 1000;\n\n //console.log('closeTime:', poll.close_date, serverTimeManager.serverTimeOffset, Date.now() / 1000 | 0);\n\n // let time = Date.now();\n // let percents = (closeTime - time) / period;\n\n // timeLeftDiv.innerHTML = String((closeTime - time) / 1000 + 1 | 0).toHHMMSS();\n\n // // @ts-ignore\n // circle.style.strokeDashoffset = circumference + percents * circumference;\n // circle.style.strokeDasharray = ${circumference} ${circumference};\n\n this.quizInterval = window.setInterval(() => {\n const time = Date.now();\n const percents = (closeTime - time) / period;\n const timeLeft = (closeTime - time) / 1000 + 1 | 0;\n timeLeftDiv.innerHTML = String(timeLeft).toHHMMSS();\n \n if (timeLeft <= 5) {\n timeLeftDiv.style.color = '#ee545c';\n circle.style.stroke = '#ee545c';\n }\n //timeLeftDiv.style.visibility = 'visible';\n\n // @ts-ignore\n circle.style.strokeDashoffset = circumference + percents * circumference;\n circle.style.strokeDasharray = `${circumference} ${circumference}`;\n\n if(time >= closeTime) {\n clearInterval(this.quizInterval);\n timeLeftDiv.innerHTML = '';\n // @ts-ignore\n circle.style.strokeDashoffset = circumference;\n this.quizInterval = 0;\n\n setTimeout(() => {\n // нужно запросить апдейт чтобы опрос обновился\n appPollsManager.getResults(this.message);\n }, 3e3);\n }\n }, 1e3);\n }\n }\n \n this.answerDivs = Array.from(this.querySelectorAll('.poll-answer')) as HTMLDivElement[];\n this.svgLines = Array.from(this.querySelectorAll('.poll-line')) as SVGSVGElement[];\n this.numberDivs = Array.from(this.querySelectorAll('.poll-answer-percents')) as HTMLDivElement[];\n\n const footerDiv = document.createElement('div');\n footerDiv.classList.add('poll-footer');\n\n this.viewResults = document.createElement('div');\n this.viewResults.className = 'poll-footer-button poll-view-results hide';\n this.viewResults.append(i18n('Chat.Poll.ViewResults'));\n\n this.votersCountDiv = document.createElement('div');\n this.votersCountDiv.className = 'poll-votes-count';\n\n footerDiv.append(this.viewResults, this.votersCountDiv);\n this.append(footerDiv);\n\n this.viewResults.addEventListener('click', (e) => {\n cancelEvent(e);\n\n if(!appSidebarRight.isTabExists(AppPollResultsTab)) {\n new AppPollResultsTab(appSidebarRight).open(this.message);\n }\n });\n ripple(this.viewResults);\n\n if(this.isMultiple) {\n this.sendVoteBtn = document.createElement('div');\n this.sendVoteBtn.classList.add('poll-footer-button', 'poll-send-vote');\n this.sendVoteBtn.append(i18n('Chat.Poll.SubmitVote'));\n ripple(this.sendVoteBtn);\n\n if(!poll.chosenIndexes.length) {\n this.votersCountDiv.classList.add('hide');\n }\n\n attachClickEvent(this.sendVoteBtn, (e) => {\n cancelEvent(e);\n /* const indexes = this.answerDivs.filter(el => el.classList.contains('is-chosing')).map(el => +el.dataset.index);\n if(indexes.length) {\n \n } */\n if(this.chosingIndexes.length) {\n this.sendVotes(this.chosingIndexes).then(() => {\n this.chosingIndexes.length = 0;\n this.answerDivs.forEach(el => {\n el.classList.remove('is-chosing');\n });\n });\n }\n });\n\n footerDiv.append(this.sendVoteBtn);\n }\n\n //const width = this.getBoundingClientRect().width;\n //this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left\n\n if(poll.chosenIndexes.length || this.isClosed) {\n this.performResults(results, poll.chosenIndexes, false);\n } else if(!this.isClosed) {\n this.setVotersCount(results);\n attachClickEvent(this, this.clickHandler);\n }\n }\n\n initQuizHint(results: PollResults) {\n if(results.solution && results.solution_entities) {\n const toggleHint = document.createElement('div');\n toggleHint.classList.add('tgico-tip', 'poll-hint');\n this.descDiv.append(toggleHint);\n\n //let active = false;\n attachClickEvent(toggleHint, (e) => {\n cancelEvent(e);\n\n //active = true;\n toggleHint.classList.add('active');\n setQuizHint(results.solution, results.solution_entities, () => {\n //active = false;\n toggleHint.classList.remove('active');\n });\n });\n\n if(this.sentVote) {\n const correctResult = results.results.find(r => r.pFlags.correct);\n if(correctResult && !correctResult.pFlags.chosen) {\n toggleHint.click();\n }\n }\n }\n }\n\n clickHandler(e: Event) {\n const target = findUpClassName(e.target, 'poll-answer') as HTMLElement;\n if(!target) {\n return;\n }\n \n cancelEvent(e);\n const answerIndex = +target.dataset.index;\n if(this.isMultiple) {\n target.classList.toggle('is-chosing');\n\n const foundIndex = this.chosingIndexes.indexOf(answerIndex);\n if(foundIndex !== -1) {\n this.chosingIndexes.splice(foundIndex, 1);\n } else {\n this.chosingIndexes.push(answerIndex);\n }\n } else {\n this.sendVotes([answerIndex]);\n }\n \n /* target.classList.add('is-voting');\n setTimeout(() => { // simulate\n this.setResults([100, 0], answerIndex);\n target.classList.remove('is-voting');\n }, 1000); */\n }\n\n sendVotes(indexes: number[]) {\n if(this.sendVotePromise) return this.sendVotePromise;\n\n const targets = this.answerDivs.filter((_, idx) => indexes.includes(idx));\n targets.forEach(target => {\n target.classList.add('is-voting');\n });\n \n this.classList.add('disable-hover');\n this.sentVote = true;\n return this.sendVotePromise = appPollsManager.sendVote(this.message, indexes).then(() => {\n targets.forEach(target => {\n target.classList.remove('is-voting');\n });\n\n this.classList.remove('disable-hover');\n }).catch(() => {\n this.sentVote = false;\n }).finally(() => {\n this.sendVotePromise = null;\n });\n }\n\n performResults(results: PollResults, chosenIndexes: number[], animate = true) {\n if(!rootScope.settings.animationsEnabled) {\n animate = false;\n }\n\n if(this.isQuiz && (results.results?.length || this.isClosed)) {\n this.answerDivs.forEach((el, idx) => {\n el.classList.toggle('is-correct', !!results.results[idx].pFlags.correct);\n });\n\n if(this.initQuizHint) {\n this.initQuizHint(results);\n this.initQuizHint = null;\n }\n\n if(this.quizInterval) {\n clearInterval(this.quizInterval);\n this.quizInterval = 0;\n }\n\n if(this.quizTimer?.parentElement) {\n this.quizTimer.remove();\n }\n\n const timeEl = this.descDiv.querySelector('.poll-time');\n if(timeEl) {\n timeEl.remove();\n }\n }\n\n if(this.isClosed) {\n this.classList.add('is-closed');\n replaceContent(this.typeDiv, i18n('Chat.Poll.Type.Closed'));\n }\n\n // set chosen\n if(this.chosenIndexes.length !== chosenIndexes.length || this.isClosed) { // if we voted\n this.isRetracted = this.chosenIndexes.length && !chosenIndexes.length;\n this.chosenIndexes = chosenIndexes.slice();\n\n if(this.isRetracted) {\n attachClickEvent(this, this.clickHandler);\n } else {\n detachClickEvent(this, this.clickHandler);\n }\n }\n \n // is need update\n if(this.chosenIndexes.length || this.isRetracted || this.isClosed) {\n const percents = results.results.map(v => results.total_voters ? v.voters / results.total_voters * 100 : 0);\n\n this.classList.toggle('no-transition', !animate);\n if(animate) {\n SetTransition(this, '', !this.isRetracted, 340);\n }\n\n fastRaf(() => {\n this.setResults(this.isRetracted ? this.percents : percents, this.chosenIndexes, animate);\n this.percents = percents;\n this.isRetracted = false;\n });\n }\n \n this.setVotersCount(results);\n\n if(this.isPublic) {\n if(!this.isMultiple) {\n this.viewResults.classList.toggle('hide', !results.total_voters || !this.chosenIndexes.length);\n this.votersCountDiv.classList.toggle('hide', !!this.chosenIndexes.length);\n }\n\n let html = '';\n /**\n * MACOS, ANDROID - без реверса\n * WINDOWS DESKTOP - реверс\n * все приложения накладывают аватарку первую на вторую, а в макете зато вторая на первую, ЛОЛ!\n */\n results.recent_voters/* .slice().reverse() */.forEach((userId, idx) => {\n const style = idx === 0 ? '' : `style=\"transform: translateX(-${idx * 3}px);\"`;\n html += `<avatar-element class=\"avatar-16\" dialog=\"0\" peer=\"${userId}\" ${style}></avatar-element>`;\n });\n this.avatarsDiv.innerHTML = html;\n }\n\n if(this.isMultiple) {\n this.sendVoteBtn.classList.toggle('hide', !!this.chosenIndexes.length);\n if(!this.chosenIndexes.length) {\n this.votersCountDiv.classList.add('hide');\n this.viewResults.classList.add('hide');\n } else if(this.isPublic) {\n this.viewResults.classList.toggle('hide', !results.total_voters || !this.chosenIndexes.length);\n this.votersCountDiv.classList.toggle('hide', !!this.chosenIndexes.length);\n } else {\n this.votersCountDiv.classList.toggle('hide', !this.chosenIndexes.length);\n }\n }\n }\n\n setResults(percents: number[], chosenIndexes: number[], animate: boolean) {\n this.svgLines.forEach(svg => svg.style.display = '');\n\n this.answerDivs.forEach((el, idx) => {\n el.classList.toggle('is-chosen', chosenIndexes.includes(idx));\n });\n\n const maxValue = Math.max(...percents);\n //this.maxLengths = percents.map(p => p / maxValue * this.maxLength);\n this.maxPercents = percents.map(p => p / maxValue);\n\n // line\n if(this.isRetracted) {\n this.svgLines.forEach((svg, idx) => {\n this.setLineProgress(idx, -1);\n });\n } else {\n const cb = () => {\n this.svgLines.forEach((svg, idx) => {\n //void svg.getBoundingClientRect(); // reflow\n this.setLineProgress(idx, 1);\n });\n };\n \n animate ? fastRaf(cb) : cb();\n }\n\n percents = percents.slice();\n roundPercents(percents);\n let getPercentValue: (percents: number, index: number) => number;\n const iterate = (i: number) => {\n percents.forEach((percents, idx) => {\n const value = getPercentValue(percents, i);\n this.numberDivs[idx].innerText = value + '%';\n });\n };\n // numbers\n if(this.isRetracted) {\n getPercentValue = (percents, index) => Math.round(percents / times * index);\n\n if(animate) {\n for(let i = (times - 1), k = 0; i >= 0; --i, ++k) {\n setTimeout(() => {\n iterate(i);\n }, oneTime * k);\n }\n } else {\n iterate(0);\n }\n } else {\n getPercentValue = (percents, index) => Math.round(percents / times * (index + 1));\n\n if(animate) {\n for(let i = 0; i < times; ++i) {\n setTimeout(() => {\n iterate(i);\n }, oneTime * i);\n }\n } else {\n iterate(times - 1);\n }\n }\n\n if(this.isRetracted) {\n if(animate) {\n this.classList.add('is-retracting');\n }\n\n this.classList.remove('is-voted');\n const cb = () => {\n this.svgLines.forEach(svg => svg.style.display = 'none');\n };\n\n if(animate) {\n setTimeout(() => {\n this.classList.remove('is-retracting');\n cb();\n }, fullTime);\n } else {\n cb();\n }\n } else {\n this.classList.add('is-voted');\n }\n }\n\n setVotersCount(results: PollResults) {\n const votersCount = results.total_voters || 0;\n let key: LangPackKey, args = [votersCount];\n if(this.isClosed) {\n if(this.isQuiz) key = votersCount ? 'Chat.Quiz.TotalVotes' : 'Chat.Quiz.TotalVotesResultEmpty';\n else key = votersCount ? 'Chat.Poll.TotalVotes1' : 'Chat.Poll.TotalVotesResultEmpty';\n } else {\n if(this.isQuiz) key = votersCount ? 'Chat.Quiz.TotalVotes' : 'Chat.Quiz.TotalVotesEmpty';\n else key = votersCount ? 'Chat.Poll.TotalVotes1' : 'Chat.Poll.TotalVotesEmpty';\n }\n \n replaceContent(this.votersCountDiv, i18n(key, args));\n }\n\n setLineProgress(index: number, multiplier: number) {\n const svg = this.svgLines[index];\n\n if(multiplier === -1) {\n svg.style.strokeDasharray = '';\n svg.style.strokeDashoffset = '';\n } else {\n //svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';\n svg.style.strokeDasharray = (multiplier * this.maxPercents[index] * 100) + '%, 485.9';\n svg.style.strokeDashoffset = '' + multiplier * this.maxOffset;\n }\n }\n\n // у элемента могут быть ещё другие методы и свойства\n}\n\ncustomElements.define(\"poll-element\", PollElement);\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type Chat from './chat/chat';\nimport { getEmojiToneIndex } from '../vendor/emoji';\nimport { readBlobAsText } from '../helpers/blob';\nimport { deferredPromise } from '../helpers/cancellablePromise';\nimport { formatDateAccordingToToday, months } from '../helpers/date';\nimport mediaSizes from '../helpers/mediaSizes';\nimport { formatBytes } from '../helpers/number';\nimport { isSafari } from '../helpers/userAgent';\nimport { PhotoSize } from '../layer';\nimport appDocsManager, { MyDocument } from \"../lib/appManagers/appDocsManager\";\nimport appMessagesManager from '../lib/appManagers/appMessagesManager';\nimport appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';\nimport LottieLoader from '../lib/lottieLoader';\nimport { attachClickEvent, cancelEvent, isInDOM } from \"../helpers/dom\";\nimport webpWorkerController from '../lib/webp/webpWorkerController';\nimport animationIntersector from './animationIntersector';\nimport appMediaPlaybackController from './appMediaPlaybackController';\nimport AudioElement from './audio';\nimport ReplyContainer from './chat/replyContainer';\nimport { Layouter, RectPart } from './groupedLayout';\nimport LazyLoadQueue from './lazyLoadQueue';\nimport PollElement from './poll';\nimport ProgressivePreloader from './preloader';\nimport './middleEllipsis';\nimport { nextRandomInt } from '../helpers/random';\nimport RichTextProcessor from '../lib/richtextprocessor';\nimport appImManager from '../lib/appManagers/appImManager';\nimport { SearchSuperContext } from './appSearchSuper.';\nimport rootScope from '../lib/rootScope';\nimport { onVideoLoad } from '../helpers/files';\nimport { animateSingle } from '../helpers/animation';\nimport renderImageFromUrl from '../helpers/dom/renderImageFromUrl';\nimport sequentialDom from '../helpers/sequentialDom';\nimport { fastRaf } from '../helpers/schedulers';\n\nconst MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB\n\nexport function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group, onlyPreview, withoutPreloader, loadPromises, noPlayButton, noAutoDownload}: {\n doc: MyDocument, \n container?: HTMLElement, \n message?: any, \n boxWidth?: number, \n boxHeight?: number, \n withTail?: boolean, \n isOut?: boolean,\n middleware?: () => boolean,\n lazyLoadQueue?: LazyLoadQueue,\n noInfo?: true,\n noPlayButton?: boolean,\n group?: string,\n onlyPreview?: boolean,\n withoutPreloader?: boolean,\n loadPromises?: Promise<any>[],\n noAutoDownload?: boolean,\n}) {\n const isAlbumItem = !(boxWidth && boxHeight);\n const canAutoplay = (doc.type !== 'video' || (doc.size <= MAX_VIDEO_AUTOPLAY_SIZE && !isAlbumItem)) \n && (doc.type === 'gif' ? rootScope.settings.autoPlay.gifs : rootScope.settings.autoPlay.videos);\n let spanTime: HTMLElement, spanPlay: HTMLElement;\n\n if(!noInfo) {\n spanTime = document.createElement('span');\n spanTime.classList.add('video-time');\n container.append(spanTime);\n \n let needPlayButton = false;\n if(doc.type !== 'gif') {\n spanTime.innerText = (doc.duration + '').toHHMMSS(false);\n\n if(!noPlayButton && doc.type !== 'round') {\n if(canAutoplay) {\n spanTime.classList.add('tgico', 'can-autoplay');\n } else {\n needPlayButton = true;\n }\n }\n } else {\n spanTime.innerText = 'GIF';\n\n if(!canAutoplay && !noPlayButton) {\n needPlayButton = true;\n noAutoDownload = undefined;\n }\n }\n\n if(needPlayButton) {\n spanPlay = document.createElement('span');\n spanPlay.classList.add('video-play', 'tgico-largeplay', 'btn-circle', 'position-center');\n container.append(spanPlay);\n }\n }\n\n let res: {\n thumb?: typeof photoRes,\n loadPromise: Promise<any>\n } = {} as any;\n\n if(doc.mime_type === 'image/gif') {\n const photoRes = wrapPhoto({\n photo: doc, \n message, \n container, \n boxWidth, \n boxHeight, \n withTail, \n isOut, \n lazyLoadQueue, \n middleware,\n withoutPreloader,\n loadPromises,\n noAutoDownload\n });\n\n res.thumb = photoRes;\n res.loadPromise = photoRes.loadPromises.full;\n return res;\n }\n\n /* const video = doc.type === 'round' ? appMediaPlaybackController.addMedia(doc, message.mid) as HTMLVideoElement : document.createElement('video');\n if(video.parentElement) {\n video.remove();\n } */\n\n const video = document.createElement('video');\n video.classList.add('media-video');\n video.setAttribute('playsinline', 'true');\n video.muted = true;\n if(doc.type === 'round') {\n const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid, !noAutoDownload) as HTMLVideoElement;\n \n const divRound = document.createElement('div');\n divRound.classList.add('media-round', 'z-depth-1');\n\n divRound.innerHTML = `<svg class=\"progress-ring\" width=\"200px\" height=\"200px\">\n <circle class=\"progress-ring__circle\" stroke=\"white\" stroke-opacity=\"0.3\" stroke-width=\"3.5\" cx=\"100\" cy=\"100\" r=\"93\" fill=\"transparent\" transform=\"rotate(-90, 100, 100)\"/>\n </svg>`;\n\n const circle = divRound.querySelector('.progress-ring__circle') as SVGCircleElement;\n const radius = circle.r.baseVal.value;\n const circumference = 2 * Math.PI * radius;\n circle.style.strokeDasharray = circumference + ' ' + circumference;\n circle.style.strokeDashoffset = '' + circumference;\n \n spanTime.classList.add('tgico');\n\n const canvas = document.createElement('canvas');\n canvas.width = canvas.height = doc.w/* * window.devicePixelRatio */;\n\n divRound.prepend(canvas, spanTime);\n divRound.append(video);\n container.append(divRound);\n\n const ctx = canvas.getContext('2d');\n /* ctx.beginPath();\n ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2);\n ctx.clip(); */\n\n const clear = () => {\n (appImManager.chat.setPeerPromise || Promise.resolve()).finally(() => {\n if(isInDOM(globalVideo)) {\n return;\n }\n\n globalVideo.removeEventListener('play', onPlay);\n globalVideo.removeEventListener('timeupdate', onTimeUpdate);\n globalVideo.removeEventListener('pause', onPaused);\n });\n };\n\n const onFrame = () => {\n ctx.drawImage(globalVideo, 0, 0);\n\n const offset = circumference - globalVideo.currentTime / globalVideo.duration * circumference;\n circle.style.strokeDashoffset = '' + offset;\n\n return !globalVideo.paused;\n };\n\n const onTimeUpdate = () => {\n if(!globalVideo.duration) return;\n\n if(!isInDOM(globalVideo)) {\n clear();\n return;\n }\n\n spanTime.innerText = (globalVideo.duration - globalVideo.currentTime + '').toHHMMSS(false);\n };\n\n const onPlay = () => {\n video.classList.add('hide');\n divRound.classList.remove('is-paused');\n animateSingle(onFrame, canvas);\n };\n\n const onPaused = () => {\n if(!isInDOM(globalVideo)) {\n clear();\n return;\n }\n\n divRound.classList.add('is-paused');\n };\n\n globalVideo.addEventListener('play', onPlay);\n globalVideo.addEventListener('timeupdate', onTimeUpdate);\n globalVideo.addEventListener('pause', onPaused);\n\n attachClickEvent(canvas, (e) => {\n cancelEvent(e);\n\n if(globalVideo.paused) {\n globalVideo.play();\n } else {\n globalVideo.pause();\n }\n });\n\n if(globalVideo.paused) {\n if(globalVideo.duration && globalVideo.currentTime !== globalVideo.duration) {\n onFrame();\n onTimeUpdate();\n video.classList.add('hide');\n } else {\n onPaused();\n }\n } else {\n onPlay();\n }\n } else {\n video.autoplay = true; // для safari\n }\n\n let photoRes: ReturnType<typeof wrapPhoto>;\n if(message) {\n photoRes = wrapPhoto({\n photo: doc, \n message, \n container, \n boxWidth, \n boxHeight, \n withTail, \n isOut, \n lazyLoadQueue, \n middleware,\n withoutPreloader: true,\n loadPromises,\n noAutoDownload\n });\n\n res.thumb = photoRes;\n\n if((!canAutoplay && doc.type !== 'gif') || onlyPreview) {\n res.loadPromise = photoRes.loadPromises.full;\n return res;\n }\n\n if(withTail) {\n const foreignObject = (photoRes.images.thumb || photoRes.images.full).parentElement;\n video.width = +foreignObject.getAttributeNS(null, 'width');\n video.height = +foreignObject.getAttributeNS(null, 'height');\n foreignObject.append(video);\n }\n } else { // * gifs masonry\n const gotThumb = appDocsManager.getThumb(doc, false);\n if(gotThumb) {\n gotThumb.promise.then(() => {\n video.poster = gotThumb.thumb.url;\n });\n }\n }\n\n if(!video.parentElement && container) {\n container.append(video);\n }\n\n let preloader: ProgressivePreloader;\n if(message?.media?.preloader) { // means upload\n preloader = message.media.preloader as ProgressivePreloader;\n preloader.attach(container, false);\n noAutoDownload = undefined;\n } else if(!doc.downloaded && !doc.supportsStreaming) {\n preloader = new ProgressivePreloader({\n attachMethod: 'prepend'\n });\n } else if(doc.supportsStreaming) {\n preloader = new ProgressivePreloader({\n cancelable: false,\n attachMethod: 'prepend'\n });\n }\n\n let f = noAutoDownload && photoRes?.preloader?.loadFunc;\n const load = () => {\n if(preloader && noAutoDownload && !withoutPreloader) {\n preloader.construct();\n preloader.setManual();\n }\n\n let loadPromise: Promise<any> = Promise.resolve();\n if(preloader) {\n if(!doc.downloaded && !doc.supportsStreaming) {\n const promise = loadPromise = appDocsManager.downloadDoc(doc, lazyLoadQueue?.queueId, noAutoDownload);\n preloader.attach(container, false, promise);\n } else if(doc.supportsStreaming) {\n if(noAutoDownload) {\n loadPromise = Promise.reject();\n } else if(!doc.downloaded) { // * check for uploading video\n preloader.attach(container, false, null);\n video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {\n preloader.detach();\n }, {once: true});\n }\n }\n }\n\n if(!noAutoDownload && f) {\n f();\n f = null;\n }\n\n noAutoDownload = undefined;\n\n const deferred = deferredPromise<void>();\n loadPromise.then(() => {\n if(middleware && !middleware()) {\n deferred.resolve();\n return;\n }\n\n if(doc.type === 'round') {\n appMediaPlaybackController.resolveWaitingForLoadMedia(message.peerId, message.mid);\n }\n\n onVideoLoad(video).then(() => {\n if(group) {\n animationIntersector.addAnimation(video, group);\n }\n \n deferred.resolve();\n });\n \n if(doc.type === 'video') {\n video.addEventListener('timeupdate', () => {\n spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false);\n });\n }\n \n video.addEventListener('error', (e) => {\n deferred.resolve();\n });\n \n video.muted = true;\n video.loop = true;\n //video.play();\n video.autoplay = true;\n\n renderImageFromUrl(video, doc.url);\n }, () => {});\n\n return {download: loadPromise, render: deferred};\n };\n\n if(preloader) {\n preloader.setDownloadFunction(load);\n }\n\n /* if(doc.size >= 20e6 && !doc.downloaded) {\n let downloadDiv = document.createElement('div');\n downloadDiv.classList.add('download');\n\n let span = document.createElement('span');\n span.classList.add('btn-circle', 'tgico-download');\n downloadDiv.append(span);\n\n downloadDiv.addEventListener('click', () => {\n downloadDiv.remove();\n loadVideo();\n });\n\n container.prepend(downloadDiv);\n\n return;\n } */\n\n if(doc.type === 'gif' && !canAutoplay) {\n attachClickEvent(container, (e) => {\n cancelEvent(e);\n spanPlay.remove();\n load();\n }, {capture: true, once: true});\n } else {\n res.loadPromise = !lazyLoadQueue ? load().render : (lazyLoadQueue.push({div: container, load: () => load().render}), Promise.resolve());\n }\n\n return res;\n}\n\nexport const formatDate = (timestamp: number, monthShort = false, withYear = true) => {\n const date = new Date(timestamp * 1000);\n \n let month = months[date.getMonth()];\n if(monthShort) month = month.slice(0, 3);\n\n let str = month + ' ' + date.getDate();\n if(withYear) {\n str += ', ' + date.getFullYear();\n }\n \n return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);\n};\n\nexport function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, noAutoDownload}: {\n message: any, \n withTime?: boolean,\n fontWeight?: number,\n voiceAsMusic?: boolean,\n showSender?: boolean,\n searchContext?: SearchSuperContext,\n loadPromises?: Promise<any>[],\n noAutoDownload?: boolean,\n}): HTMLElement {\n if(!fontWeight) fontWeight = 500;\n\n const doc = (message.media.document || message.media.webpage.document) as MyDocument;\n const uploading = message.pFlags.is_outgoing && message.media?.preloader;\n if(doc.type === 'audio' || doc.type === 'voice') {\n const audioElement = new AudioElement();\n audioElement.setAttribute('message-id', '' + message.mid);\n audioElement.setAttribute('peer-id', '' + message.peerId);\n audioElement.withTime = withTime;\n audioElement.message = message;\n audioElement.noAutoDownload = noAutoDownload;\n \n if(voiceAsMusic) audioElement.voiceAsMusic = voiceAsMusic;\n if(searchContext) audioElement.searchContext = searchContext;\n if(showSender) audioElement.showSender = showSender;\n \n if(uploading) {\n audioElement.preloader = message.media.preloader;\n }\n\n audioElement.dataset.fontWeight = '' + fontWeight;\n audioElement.render();\n return audioElement;\n }\n\n let extSplitted = doc.file_name ? doc.file_name.split('.') : '';\n let ext = '';\n ext = extSplitted.length > 1 && Array.isArray(extSplitted) ? extSplitted.pop().toLowerCase() : 'file';\n\n let docDiv = document.createElement('div');\n docDiv.classList.add('document', `ext-${ext}`);\n docDiv.dataset.docId = doc.id;\n\n const icoDiv = document.createElement('div');\n icoDiv.classList.add('document-ico');\n\n if(doc.thumbs?.length || (message.pFlags.is_outgoing && doc.url && doc.type === 'photo')) {\n docDiv.classList.add('document-with-thumb');\n\n let imgs: HTMLImageElement[] = [];\n if(message.pFlags.is_outgoing) {\n icoDiv.innerHTML = `<img src=\"${doc.url}\">`;\n imgs.push(icoDiv.firstElementChild as HTMLImageElement);\n } else {\n const wrapped = wrapPhoto({\n photo: doc, \n message: null, \n container: icoDiv, \n boxWidth: 54, \n boxHeight: 54,\n loadPromises,\n withoutPreloader: true\n });\n icoDiv.style.width = icoDiv.style.height = '';\n if(wrapped.images.thumb) imgs.push(wrapped.images.thumb);\n if(wrapped.images.full) imgs.push(wrapped.images.full);\n }\n\n imgs.forEach(img => img.classList.add('document-thumb'));\n } else {\n icoDiv.innerText = ext;\n }\n\n //let fileName = stringMiddleOverflow(doc.file_name || 'Unknown.file', 26);\n let fileName = doc.file_name || 'Unknown.file';\n let size = formatBytes(doc.size);\n \n if(withTime) {\n size += ' · ' + formatDate(doc.date);\n }\n\n if(showSender) {\n size += ' · ' + appMessagesManager.getSenderToPeerText(message);\n }\n\n let titleAdditionHTML = '';\n if(showSender) {\n titleAdditionHTML = `<div class=\"sent-time\">${formatDateAccordingToToday(new Date(message.date * 1000))}</div>`;\n }\n \n docDiv.innerHTML = `\n ${doc.downloaded && !uploading ? '' : `<div class=\"document-download\"></div>`}\n <div class=\"document-name\"><middle-ellipsis-element data-font-weight=\"${fontWeight}\">${fileName}</middle-ellipsis-element>${titleAdditionHTML}</div>\n <div class=\"document-size\">${size}</div>\n `;\n\n docDiv.prepend(icoDiv);\n\n if(!uploading && message.pFlags.is_outgoing) {\n return docDiv;\n }\n\n let downloadDiv: HTMLElement, preloader: ProgressivePreloader = null;\n const onLoad = () => {\n if(downloadDiv) {\n downloadDiv.classList.add('downloaded');\n const _downloadDiv = downloadDiv;\n setTimeout(() => {\n _downloadDiv.remove();\n }, 200);\n downloadDiv = null;\n }\n\n if(preloader) {\n preloader = null;\n }\n };\n\n const load = () => {\n const doc = appDocsManager.getDoc(docDiv.dataset.docId);\n const download = appDocsManager.saveDocFile(doc, appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : 0);\n\n if(downloadDiv) {\n download.then(onLoad);\n preloader.attach(downloadDiv, true, download);\n }\n\n return {download};\n };\n\n if(!(doc.downloaded && !uploading)) {\n downloadDiv = docDiv.querySelector('.document-download');\n preloader = message.media.preloader as ProgressivePreloader;\n\n if(!preloader) {\n preloader = new ProgressivePreloader();\n\n preloader.construct();\n preloader.setManual();\n preloader.attach(downloadDiv);\n preloader.setDownloadFunction(load);\n } else {\n preloader.attach(downloadDiv);\n message.media.promise.then(onLoad);\n }\n }\n\n attachClickEvent(docDiv, (e) => {\n if(preloader) {\n preloader.onClick(e);\n } else {\n load();\n }\n });\n \n return docDiv;\n}\n\nfunction wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, message: string}, container: HTMLElement, boxWidth: number, boxHeight: number, isOut: boolean) {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.classList.add('bubble__media-container', isOut ? 'is-out' : 'is-in');\n \n const foreignObject = document.createElementNS(\"http://www.w3.org/2000/svg\", 'foreignObject');\n\n const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, true);\n if(gotThumb) {\n foreignObject.append(gotThumb.image);\n }\n appPhotosManager.setAttachmentSize(photo, foreignObject, boxWidth, boxHeight);\n \n const width = +foreignObject.getAttributeNS(null, 'width');\n const height = +foreignObject.getAttributeNS(null, 'height');\n\n svg.setAttributeNS(null, 'width', '' + width);\n svg.setAttributeNS(null, 'height', '' + height);\n\n svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height);\n svg.setAttributeNS(null, 'preserveAspectRatio', 'none');\n\n const clipId = 'clip' + message.mid + '_' + nextRandomInt(9999);\n svg.dataset.clipId = clipId;\n \n const defs = document.createElementNS(\"http://www.w3.org/2000/svg\", 'defs');\n let clipPathHTML: string = '';\n \n if(message.message) {\n //clipPathHTML += `<rect width=\"${width}\" height=\"${height}\"></rect>`;\n } else {\n if(isOut) {\n clipPathHTML += `\n <use href=\"#message-tail\" transform=\"translate(${width - 2}, ${height}) scale(-1, -1)\"></use>\n <path />\n `;\n } else {\n clipPathHTML += `\n <use href=\"#message-tail\" transform=\"translate(2, ${height}) scale(1, -1)\"></use>\n <path />\n `;\n }\n }\n\n defs.innerHTML = `<clipPath id=\"${clipId}\">${clipPathHTML}</clipPath>`;\n \n container.style.width = parseInt(container.style.width) - 9 + 'px';\n container.classList.add('with-tail');\n\n svg.append(defs, foreignObject);\n container.append(svg);\n\n let img = foreignObject.firstElementChild as HTMLImageElement;\n if(!img) {\n foreignObject.append(img = new Image());\n }\n\n return img;\n}\n\nexport function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, noAutoDownload, noBlur}: {\n photo: MyPhoto | MyDocument, \n message: any, \n container: HTMLElement, \n boxWidth?: number, \n boxHeight?: number, \n withTail?: boolean, \n isOut?: boolean, \n lazyLoadQueue?: LazyLoadQueue, \n middleware?: () => boolean, \n size?: PhotoSize,\n withoutPreloader?: boolean,\n loadPromises?: Promise<any>[],\n noAutoDownload?: boolean,\n noBlur?: boolean,\n}) {\n if(!((photo as MyPhoto).sizes || (photo as MyDocument).thumbs)) {\n if(boxWidth && boxHeight && photo._ === 'document') {\n size = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message && message.message);\n }\n\n return {\n loadPromises: {\n thumb: Promise.resolve(),\n full: Promise.resolve()\n },\n images: {\n thumb: null,\n full: null\n },\n preloader: null\n };\n }\n\n if(boxWidth === undefined) boxWidth = mediaSizes.active.regular.width;\n if(boxHeight === undefined) boxHeight = mediaSizes.active.regular.height;\n\n let loadThumbPromise: Promise<any>;\n let thumbImage: HTMLImageElement;\n let image: HTMLImageElement;\n if(withTail) {\n image = wrapMediaWithTail(photo, message, container, boxWidth, boxHeight, isOut);\n } else {\n image = new Image();\n\n if(boxWidth && boxHeight) { // !album\n size = appPhotosManager.setAttachmentSize(photo, container, boxWidth, boxHeight, undefined, message && message.message);\n }\n\n const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(photo, !noBlur);\n if(gotThumb) {\n loadThumbPromise = gotThumb.loadPromise;\n thumbImage = gotThumb.image;\n thumbImage.classList.add('media-photo');\n container.append(thumbImage);\n }\n }\n\n image.classList.add('media-photo');\n \n //console.log('wrapPhoto downloaded:', photo, photo.downloaded, container);\n \n const cacheContext = appPhotosManager.getCacheContext(photo);\n\n const needFadeIn = (thumbImage || !cacheContext.downloaded) && rootScope.settings.animationsEnabled;\n if(needFadeIn) {\n image.classList.add('fade-in');\n }\n\n let preloader: ProgressivePreloader;\n if(message?.media?.preloader) { // means upload\n preloader = message.media.preloader;\n preloader.attach(container);\n noAutoDownload = undefined;\n } else {\n preloader = new ProgressivePreloader({\n attachMethod: 'prepend'\n });\n }\n\n const getDownloadPromise = () => {\n const promise = photo._ === 'document' && photo.mime_type === 'image/gif' ? \n appDocsManager.downloadDoc(photo, /* undefined, */lazyLoadQueue?.queueId) : \n appPhotosManager.preloadPhoto(photo, size, lazyLoadQueue?.queueId, noAutoDownload);\n\n noAutoDownload = undefined;\n\n return promise;\n };\n\n const onLoad = (): Promise<void> => {\n if(middleware && !middleware()) return Promise.resolve();\n\n return new Promise((resolve) => {\n renderImageFromUrl(image, cacheContext.url || photo.url, () => {\n sequentialDom.mutateElement(container, () => {\n container.append(image);\n\n fastRaf(() => {\n resolve();\n });\n \n if(needFadeIn) {\n image.addEventListener('animationend', () => {\n sequentialDom.mutate(() => {\n image.classList.remove('fade-in');\n \n if(thumbImage) {\n thumbImage.remove();\n }\n });\n }, {once: true});\n }\n });\n });\n });\n };\n\n let loadPromise: Promise<any>;\n const load = () => {\n if(noAutoDownload && !withoutPreloader) {\n preloader.construct();\n preloader.setManual();\n }\n\n const promise = getDownloadPromise();\n\n if(!cacheContext.downloaded && !withoutPreloader && (size as PhotoSize.photoSize).w >= 150 && (size as PhotoSize.photoSize).h >= 150) {\n preloader.attach(container, false, promise);\n }\n\n const renderPromise = promise.then(onLoad);\n renderPromise.catch(() => {});\n return {download: promise, render: renderPromise};\n };\n\n preloader.setDownloadFunction(load);\n \n if(cacheContext.downloaded) {\n loadThumbPromise = loadPromise = load().render;\n } else {\n if(!lazyLoadQueue) loadPromise = load().render;\n /* else if(noAutoDownload) {\n preloader.construct();\n preloader.setManual();\n preloader.attach(container);\n } */ else lazyLoadQueue.push({div: container, load: () => load().download});\n }\n\n if(loadPromises && loadThumbPromise) {\n loadPromises.push(loadThumbPromise);\n }\n\n return {\n loadPromises: {\n thumb: loadThumbPromise,\n full: loadPromise || Promise.resolve()\n },\n images: {\n thumb: thumbImage,\n full: image\n },\n preloader\n };\n}\n\nexport function wrapSticker({doc, div, middleware, lazyLoadQueue, group, play, onlyThumb, emoji, width, height, withThumb, loop, loadPromises, needFadeIn}: {\n doc: MyDocument, \n div: HTMLElement, \n middleware?: () => boolean, \n lazyLoadQueue?: LazyLoadQueue, \n group?: string, \n play?: boolean, \n onlyThumb?: boolean,\n emoji?: string,\n width?: number,\n height?: number,\n withThumb?: boolean,\n loop?: boolean,\n loadPromises?: Promise<any>[],\n needFadeIn?: boolean,\n}) {\n const stickerType = doc.sticker;\n\n if(!width) {\n width = !emoji ? 200 : undefined;\n }\n\n if(!height) {\n height = !emoji ? 200 : undefined;\n }\n\n if(stickerType === 2 && !LottieLoader.loaded) {\n //LottieLoader.loadLottie();\n LottieLoader.loadLottieWorkers();\n }\n \n if(!stickerType) {\n console.error('wrong doc for wrapSticker!', doc);\n throw new Error('wrong doc for wrapSticker!');\n }\n\n div.dataset.docId = doc.id;\n div.classList.add('media-sticker-wrapper');\n \n //console.log('wrap sticker', doc, div, onlyThumb);\n\n const toneIndex = emoji ? getEmojiToneIndex(emoji) : -1;\n const downloaded = doc.downloaded && !needFadeIn;\n \n let loadThumbPromise = deferredPromise<void>();\n let haveThumbCached = false;\n if((doc.thumbs?.length || doc.stickerCachedThumbs) && !div.firstElementChild && (!downloaded || stickerType === 2 || onlyThumb)/* && doc.thumbs[0]._ !== 'photoSizeEmpty' */) {\n let thumb = doc.stickerCachedThumbs && doc.stickerCachedThumbs[toneIndex] || doc.thumbs[0];\n \n //console.log('wrap sticker', thumb, div);\n\n let thumbImage: HTMLImageElement;\n const afterRender = () => {\n if(!div.childElementCount) {\n thumbImage.classList.add('media-sticker', 'thumbnail');\n \n sequentialDom.mutateElement(div, () => {\n div.append(thumbImage);\n loadThumbPromise.resolve();\n });\n }\n };\n\n if('url' in thumb) {\n thumbImage = new Image();\n renderImageFromUrl(thumbImage, thumb.url, afterRender);\n haveThumbCached = true;\n } else if('bytes' in thumb) {\n if(thumb._ === 'photoPathSize') {\n if(thumb.bytes.length) {\n const d = appPhotosManager.getPathFromPhotoPathSize(thumb);\n div.innerHTML = `<svg class=\"rlottie-vector media-sticker thumbnail\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 ${doc.w || 512} ${doc.h || 512}\" xml:space=\"preserve\">\n <path d=\"${d}\"/>\n </svg>`;\n } else {\n thumb = doc.thumbs.find(t => (t as PhotoSize.photoStrippedSize).bytes?.length) || thumb;\n }\n } \n \n if(thumb && thumb._ !== 'photoPathSize' && toneIndex <= 0) {\n thumbImage = new Image();\n\n if((webpWorkerController.isWebpSupported() || doc.pFlags.stickerThumbConverted || thumb.url)/* && false */) {\n renderImageFromUrl(thumbImage, appPhotosManager.getPreviewURLFromThumb(thumb as PhotoSize.photoStrippedSize, true), afterRender);\n haveThumbCached = true;\n } else {\n webpWorkerController.convert(doc.id, (thumb as PhotoSize.photoStrippedSize).bytes as Uint8Array).then(bytes => {\n (thumb as PhotoSize.photoStrippedSize).bytes = bytes;\n doc.pFlags.stickerThumbConverted = true;\n \n if(middleware && !middleware()) return;\n \n if(!div.childElementCount) {\n renderImageFromUrl(thumbImage, appPhotosManager.getPreviewURLFromThumb(thumb as PhotoSize.photoStrippedSize, true), afterRender);\n }\n }).catch(() => {});\n }\n }\n } else if(stickerType === 2 && (withThumb || onlyThumb) && toneIndex <= 0) {\n thumbImage = new Image();\n\n const load = () => {\n if(div.childElementCount || (middleware && !middleware())) return;\n\n const r = () => {\n if(div.childElementCount || (middleware && !middleware())) return;\n renderImageFromUrl(thumbImage, (thumb as PhotoSize.photoStrippedSize).url, afterRender);\n };\n \n if((thumb as PhotoSize.photoStrippedSize).url) {\n r();\n return Promise.resolve();\n } else {\n return appDocsManager.getThumbURL(doc, thumb as PhotoSize.photoStrippedSize).promise.then(r);\n }\n };\n \n if(lazyLoadQueue && onlyThumb) {\n lazyLoadQueue.push({div, load});\n return Promise.resolve();\n } else {\n load();\n\n if((thumb as any).url) {\n haveThumbCached = true;\n }\n }\n }\n }\n\n if(loadPromises && haveThumbCached) {\n loadPromises.push(loadThumbPromise);\n }\n\n if(onlyThumb) { // for sticker panel\n return Promise.resolve();\n }\n \n const load = async() => {\n if(middleware && !middleware()) return;\n\n if(stickerType === 2) {\n /* if(doc.id === '1860749763008266301') {\n console.log('loaded sticker:', doc, div);\n } */\n\n //await new Promise((resolve) => setTimeout(resolve, 500));\n //return;\n\n //console.time('download sticker' + doc.id);\n\n //appDocsManager.downloadDocNew(doc.id).promise.then(res => res.json()).then(async(json) => {\n //fetch(doc.url).then(res => res.json()).then(async(json) => {\n /* return */ await appDocsManager.downloadDoc(doc, /* undefined, */lazyLoadQueue?.queueId)\n .then(readBlobAsText)\n //.then(JSON.parse)\n .then(async(json) => {\n //console.timeEnd('download sticker' + doc.id);\n //console.log('loaded sticker:', doc, div/* , blob */);\n if(middleware && !middleware()) return;\n\n let animation = await LottieLoader.loadAnimationWorker({\n container: div,\n loop: loop && !emoji,\n autoplay: play,\n animationData: json,\n width,\n height\n }, group, toneIndex);\n\n //const deferred = deferredPromise<void>();\n \n animation.addEventListener('firstFrame', () => {\n const element = div.firstElementChild;\n needFadeIn = (needFadeIn || !element || element.tagName === 'svg') && rootScope.settings.animationsEnabled;\n\n const cb = () => {\n if(element && element !== animation.canvas) {\n element.remove();\n }\n };\n\n if(!needFadeIn) {\n if(element) {\n sequentialDom.mutate(cb);\n }\n } else {\n sequentialDom.mutate(() => {\n animation.canvas.classList.add('fade-in');\n if(element) {\n element.classList.add('fade-out');\n }\n \n animation.canvas.addEventListener('animationend', () => {\n sequentialDom.mutate(() => {\n animation.canvas.classList.remove('fade-in');\n cb();\n });\n }, {once: true});\n });\n }\n\n appDocsManager.saveLottiePreview(doc, animation.canvas, toneIndex);\n\n //deferred.resolve();\n }, true);\n \n if(emoji) {\n attachClickEvent(div, (e) => {\n cancelEvent(e);\n let animation = LottieLoader.getAnimation(div);\n \n if(animation.paused) {\n animation.autoplay = true;\n animation.restart();\n }\n });\n }\n\n //return deferred;\n //await new Promise((resolve) => setTimeout(resolve, 5e3));\n });\n\n //console.timeEnd('render sticker' + doc.id);\n } else if(stickerType === 1) {\n const image = new Image();\n const thumbImage = div.firstElementChild !== image && div.firstElementChild;\n needFadeIn = (needFadeIn || !downloaded || thumbImage) && rootScope.settings.animationsEnabled;\n\n image.classList.add('media-sticker');\n\n if(needFadeIn) {\n image.classList.add('fade-in');\n }\n\n return new Promise<void>((resolve, reject) => {\n const r = () => {\n if(middleware && !middleware()) return resolve();\n \n renderImageFromUrl(image, doc.url, () => {\n sequentialDom.mutateElement(div, () => {\n div.append(image);\n if(thumbImage) {\n thumbImage.classList.add('fade-out');\n }\n\n resolve();\n\n if(needFadeIn) {\n image.addEventListener('animationend', () => {\n image.classList.remove('fade-in');\n if(thumbImage) {\n thumbImage.remove();\n }\n }, {once: true});\n }\n });\n });\n };\n \n if(doc.url) r();\n else {\n appDocsManager.downloadDoc(doc, /* undefined, */lazyLoadQueue?.queueId).then(r, resolve);\n }\n });\n }\n };\n\n const loadPromise: Promise<any> = lazyLoadQueue && (!downloaded || stickerType === 2) ? \n (lazyLoadQueue.push({div, load}), Promise.resolve()) : \n load();\n\n if(downloaded && stickerType === 1) {\n loadThumbPromise = loadPromise;\n if(loadPromises) {\n loadPromises.push(loadThumbPromise);\n }\n }\n\n return loadPromise;\n}\n\nexport function wrapReply(title: string, subtitle: string, message?: any) {\n const replyContainer = new ReplyContainer('reply');\n replyContainer.fill(title, subtitle, message);\n /////////console.log('wrapReply', title, subtitle, media);\n return replyContainer.container;\n}\n\nexport function prepareAlbum(options: {\n container: HTMLElement,\n items: {w: number, h: number}[],\n maxWidth: number,\n minWidth: number,\n spacing: number,\n maxHeight?: number,\n forMedia?: true\n}) {\n const layouter = new Layouter(options.items, options.maxWidth, options.minWidth, options.spacing, options.maxHeight);\n const layout = layouter.layout();\n\n const widthItem = layout.find(item => item.sides & RectPart.Right);\n const width = widthItem.geometry.width + widthItem.geometry.x;\n\n const heightItem = layout.find(item => item.sides & RectPart.Bottom);\n const height = heightItem.geometry.height + heightItem.geometry.y;\n\n const container = options.container;\n container.style.width = width + 'px';\n container.style.height = height + 'px';\n const children = container.children;\n\n layout.forEach(({geometry, sides}, idx) => {\n let div: HTMLElement;\n div = children[idx] as HTMLElement;\n if(!div) {\n div = document.createElement('div');\n container.append(div);\n }\n\n div.classList.add('album-item', 'grouped-item');\n\n div.style.width = (geometry.width / width * 100) + '%';\n div.style.height = (geometry.height / height * 100) + '%';\n div.style.top = (geometry.y / height * 100) + '%';\n div.style.left = (geometry.x / width * 100) + '%';\n\n if(sides & RectPart.Left && sides & RectPart.Top) {\n div.style.borderTopLeftRadius = 'inherit';\n }\n\n if(sides & RectPart.Left && sides & RectPart.Bottom) {\n div.style.borderBottomLeftRadius = 'inherit';\n }\n\n if(sides & RectPart.Right && sides & RectPart.Top) {\n div.style.borderTopRightRadius = 'inherit';\n }\n\n if(sides & RectPart.Right && sides & RectPart.Bottom) {\n div.style.borderBottomRightRadius = 'inherit';\n }\n\n if(options.forMedia) {\n const mediaDiv = document.createElement('div');\n mediaDiv.classList.add('album-item-media');\n \n div.append(mediaDiv);\n }\n\n // @ts-ignore\n //div.style.backgroundColor = '#' + Math.floor(Math.random() * (2 ** 24 - 1)).toString(16).padStart(6, '0');\n });\n\n /* if(options.forMedia) {\n layout.forEach((_, i) => {\n const mediaDiv = document.createElement('div');\n mediaDiv.classList.add('album-item-media');\n \n options.container.children[i].append(mediaDiv);\n });\n } */\n}\n\nexport function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, noAutoDownload}: {\n groupId: string, \n attachmentDiv: HTMLElement,\n middleware?: () => boolean,\n lazyLoadQueue?: LazyLoadQueue,\n uploading?: boolean,\n isOut: boolean,\n chat: Chat,\n loadPromises?: Promise<any>[],\n noAutoDownload?: boolean,\n}) {\n const items: {size: PhotoSize.photoSize, media: any, message: any}[] = [];\n\n // !lowest msgID will be the FIRST in album\n const storage = appMessagesManager.getMidsByAlbum(groupId);\n for(const mid of storage) {\n const m = chat.getMessage(mid);\n const media = m.media.photo || m.media.document;\n\n const size: any = media._ === 'photo' ? appPhotosManager.choosePhotoSize(media, 480, 480) : {w: media.w, h: media.h};\n items.push({size, media, message: m});\n }\n\n /* // * pending\n if(storage[0] < 0) {\n items.reverse();\n } */\n\n prepareAlbum({\n container: attachmentDiv,\n items: items.map(i => ({w: i.size.w, h: i.size.h})),\n maxWidth: mediaSizes.active.album.width,\n minWidth: 100,\n spacing: 2,\n forMedia: true\n });\n\n items.forEach((item, idx) => {\n const {size, media, message} = item;\n\n const div = attachmentDiv.children[idx] as HTMLElement;\n div.dataset.mid = '' + message.mid;\n const mediaDiv = div.firstElementChild as HTMLElement;\n if(media._ === 'photo') {\n wrapPhoto({\n photo: media,\n message,\n container: mediaDiv,\n boxWidth: 0,\n boxHeight: 0,\n isOut,\n lazyLoadQueue,\n middleware,\n size,\n loadPromises,\n noAutoDownload\n });\n } else {\n wrapVideo({\n doc: message.media.document,\n container: mediaDiv,\n message,\n boxWidth: 0,\n boxHeight: 0,\n withTail: false,\n isOut,\n lazyLoadQueue,\n middleware,\n loadPromises,\n noAutoDownload\n });\n }\n });\n}\n\nexport function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat, loadPromises, noAutoDownload}: {\n albumMustBeRenderedFull: boolean,\n message: any,\n messageDiv: HTMLElement,\n bubble: HTMLElement,\n uploading?: boolean,\n chat: Chat,\n loadPromises?: Promise<any>[],\n noAutoDownload?: boolean,\n}) {\n let nameContainer: HTMLElement;\n const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];\n /* if(isPending) {\n mids.reverse();\n } */\n\n mids.forEach((mid, idx) => {\n const message = chat.getMessage(mid);\n const div = wrapDocument({\n message,\n loadPromises,\n noAutoDownload\n });\n\n const container = document.createElement('div');\n container.classList.add('document-container');\n container.dataset.mid = '' + mid;\n\n const wrapper = document.createElement('div');\n wrapper.classList.add('document-wrapper');\n \n if(message.message) {\n const messageDiv = document.createElement('div');\n messageDiv.classList.add('document-message');\n\n const richText = RichTextProcessor.wrapRichText(message.message, {\n entities: message.totalEntities\n });\n\n messageDiv.innerHTML = richText;\n wrapper.append(messageDiv);\n }\n\n if(mids.length > 1) {\n const selection = document.createElement('div');\n selection.classList.add('document-selection');\n container.append(selection);\n \n container.classList.add('grouped-item');\n\n if(idx === 0) {\n nameContainer = wrapper;\n }\n }\n\n wrapper.append(div);\n container.append(wrapper);\n messageDiv.append(container);\n });\n\n if(mids.length > 1) {\n bubble.classList.add('is-multiple-documents', 'is-grouped');\n }\n\n return nameContainer;\n}\n\nexport function wrapPoll(message: any) {\n const elem = new PollElement();\n elem.message = message;\n elem.setAttribute('peer-id', '' + message.peerId);\n elem.setAttribute('poll-id', message.media.poll.id);\n elem.setAttribute('message-id', '' + message.mid);\n elem.render();\n return elem;\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\n// * will change .cleaned and new instance will be created\nexport const getMiddleware = () => {\n let cleanupObj = {cleaned: false};\n return {\n clean: () => {\n cleanupObj.cleaned = true;\n cleanupObj = {cleaned: false};\n },\n get: () => {\n const _cleanupObj = cleanupObj;\n return () => {\n return !_cleanupObj.cleaned;\n };\n }\n };\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDialogsManager, { DialogDom } from \"../lib/appManagers/appDialogsManager\";\nimport { isInDOM, positionElementByIndex, replaceContent } from \"../helpers/dom\";\nimport { getHeavyAnimationPromise } from \"../hooks/useHeavyAnimationCheck\";\nimport appUsersManager from \"../lib/appManagers/appUsersManager\";\nimport { insertInDescendSortedArray } from \"../helpers/array\";\n\ntype SortedUser = {\n peerId: number, \n status: number, \n dom: DialogDom\n};\nexport default class SortedUserList {\n public static SORT_INTERVAL = 30e3;\n public list: HTMLUListElement;\n public users: Map<number, SortedUser>;\n public sorted: Array<SortedUser>;\n\n constructor() {\n this.list = appDialogsManager.createChatList();\n\n this.users = new Map();\n this.sorted = [];\n\n let timeout: number;\n const doTimeout = () => {\n timeout = window.setTimeout(() => {\n this.updateList().then((good) => {\n if(good) {\n doTimeout();\n }\n });\n }, SortedUserList.SORT_INTERVAL);\n };\n\n doTimeout();\n }\n\n public async updateList() {\n if(!isInDOM(this.list)) {\n return false;\n }\n\n await getHeavyAnimationPromise();\n\n if(!isInDOM(this.list)) {\n return false;\n }\n\n this.users.forEach(user => {\n this.update(user.peerId, true);\n });\n\n this.sorted.forEach((sortedUser, idx) => {\n positionElementByIndex(sortedUser.dom.listEl, this.list, idx);\n });\n\n return true;\n }\n\n public add(peerId: number) {\n if(this.users.has(peerId)) {\n return;\n }\n\n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: false,\n drawStatus: false,\n avatarSize: 48,\n autonomous: true,\n meAsSaved: false,\n rippleEnabled: false\n });\n\n const sortedUser: SortedUser = {\n peerId,\n status: appUsersManager.getUserStatusForSort(peerId),\n dom\n };\n\n this.users.set(peerId, sortedUser);\n this.update(peerId);\n }\n\n public update(peerId: number, batch = false) {\n const sortedUser = this.users.get(peerId);\n sortedUser.status = appUsersManager.getUserStatusForSort(peerId);\n const status = appUsersManager.getUserStatusString(peerId);\n replaceContent(sortedUser.dom.lastMessageSpan, status);\n\n const idx = insertInDescendSortedArray(this.sorted, sortedUser, 'status');\n if(!batch) {\n positionElementByIndex(sortedUser.dom.listEl, this.list, idx);\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { formatDateAccordingToToday, months } from \"../helpers/date\";\nimport { positionElementByIndex } from \"../helpers/dom\";\nimport { copy, getObjectKeysAndSort, safeAssign } from \"../helpers/object\";\nimport { escapeRegExp, limitSymbols } from \"../helpers/string\";\nimport appChatsManager from \"../lib/appManagers/appChatsManager\";\nimport appDialogsManager, { DialogDom } from \"../lib/appManagers/appDialogsManager\";\nimport appMessagesManager, { MyInputMessagesFilter, MyMessage } from \"../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../lib/appManagers/appPeersManager\";\nimport appPhotosManager from \"../lib/appManagers/appPhotosManager\";\nimport appStateManager from \"../lib/appManagers/appStateManager\";\nimport appUsersManager from \"../lib/appManagers/appUsersManager\";\nimport { logger } from \"../lib/logger\";\nimport RichTextProcessor from \"../lib/richtextprocessor\";\nimport rootScope from \"../lib/rootScope\";\nimport searchIndexManager from \"../lib/searchIndexManager\";\nimport AppMediaViewer from \"./appMediaViewer\";\nimport { SearchGroup, SearchGroupType } from \"./appSearch\";\nimport { horizontalMenu } from \"./horizontalMenu\";\nimport LazyLoadQueue from \"./lazyLoadQueue\";\nimport { putPreloader, formatPhoneNumber } from \"./misc\";\nimport { ripple } from \"./ripple\";\nimport Scrollable, { ScrollableX } from \"./scrollable\";\nimport { wrapDocument, wrapPhoto, wrapVideo } from \"./wrappers\";\nimport useHeavyAnimationCheck, { getHeavyAnimationPromise } from \"../hooks/useHeavyAnimationCheck\";\nimport { isSafari } from \"../helpers/userAgent\";\nimport { LangPackKey, i18n } from \"../lib/langPack\";\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\nimport { getMiddleware } from \"../helpers/middleware\";\nimport appProfileManager from \"../lib/appManagers/appProfileManager\";\nimport { ChannelParticipant, ChatFull, ChatParticipant, ChatParticipants } from \"../layer\";\nimport SortedUserList from \"./sortedUserList\";\nimport findUpTag from \"../helpers/dom/findUpTag\";\nimport appSidebarRight from \"./sidebarRight\";\nimport mediaSizes from \"../helpers/mediaSizes\";\nimport appImManager from \"../lib/appManagers/appImManager\";\n\n//const testScroll = false;\n\nexport type SearchSuperType = MyInputMessagesFilter/* | 'members' */;\nexport type SearchSuperContext = {\n peerId: number,\n inputFilter: MyInputMessagesFilter,\n query?: string,\n maxId?: number,\n folderId?: number,\n threadId?: number,\n date?: number,\n nextRate?: number,\n minDate?: number,\n maxDate?: number\n};\n\nexport type SearchSuperMediaType = 'members' | 'media' | 'files' | 'links' | 'music' | 'chats' | 'voice';\nexport type SearchSuperMediaTab = {\n inputFilter: SearchSuperType,\n name: LangPackKey,\n type: SearchSuperMediaType,\n contentTab?: HTMLElement,\n menuTab?: HTMLElement,\n scroll?: {scrollTop: number, scrollHeight: number}\n};\n\nexport default class AppSearchSuper {\n public tabs: {[t in SearchSuperType]: HTMLDivElement} = {} as any;\n\n public mediaTab: SearchSuperMediaTab;\n\n public container: HTMLElement;\n public nav: HTMLElement;\n private navScrollableContainer: HTMLDivElement;\n private tabsContainer: HTMLElement;\n private tabsMenu: HTMLElement;\n private prevTabId = -1;\n \n private lazyLoadQueue = new LazyLoadQueue();\n public middleware = getMiddleware();\n\n public historyStorage: Partial<{[type in SearchSuperType]: {mid: number, peerId: number}[]}> = {};\n public usedFromHistory: Partial<{[type in SearchSuperType]: number}> = {};\n public urlsToRevoke: string[] = [];\n\n private searchContext: SearchSuperContext;\n public loadMutex: Promise<any> = Promise.resolve();\n\n private nextRates: Partial<{[type in SearchSuperType]: number}> = {};\n private loadPromises: Partial<{[type in SearchSuperType]: Promise<void>}> = {};\n private loaded: Partial<{[type in SearchSuperType]: boolean}> = {};\n private loadedChats = false;\n private firstLoad = true;\n\n private log = logger('SEARCH-SUPER');\n public selectTab: ReturnType<typeof horizontalMenu>;\n \n private monthContainers: Partial<{\n [type in SearchSuperType]: {\n [timestamp: number]: {\n container: HTMLElement,\n items: HTMLElement\n }\n }\n }> = {};\n\n private searchGroupMedia: SearchGroup;\n\n public mediaTabsMap: Map<SearchSuperMediaType, SearchSuperMediaTab> = new Map();\n\n private membersList: SortedUserList;\n\n private skipScroll: boolean;\n\n // * arguments\n public mediaTabs: SearchSuperMediaTab[];\n public scrollable: Scrollable;\n public searchGroups?: {[group in SearchGroupType]: SearchGroup};\n public asChatList? = false;\n public groupByMonth? = true;\n public hideEmptyTabs? = true;\n public onChangeTab?: (mediaTab: SearchSuperMediaTab) => void;\n public showSender? = false;\n\n constructor(options: Pick<AppSearchSuper, 'mediaTabs' | 'scrollable' | 'searchGroups' | 'asChatList' | 'groupByMonth' | 'hideEmptyTabs' | 'onChangeTab' | 'showSender'>) {\n safeAssign(this, options);\n\n this.container = document.createElement('div');\n this.container.classList.add('search-super');\n\n const navScrollableContainer = this.navScrollableContainer = document.createElement('div');\n navScrollableContainer.classList.add('search-super-tabs-scrollable', 'menu-horizontal-scrollable', 'sticky');\n\n const navScrollable = new ScrollableX(navScrollableContainer);\n\n const nav = this.nav = document.createElement('nav');\n nav.classList.add('search-super-tabs', 'menu-horizontal-div');\n this.tabsMenu = nav;\n\n navScrollable.container.append(nav);\n\n for(const mediaTab of this.mediaTabs) {\n const menuTab = document.createElement('div');\n menuTab.classList.add('menu-horizontal-div-item');\n const span = document.createElement('span');\n const i = document.createElement('i');\n\n span.append(i18n(mediaTab.name));\n span.append(i);\n\n menuTab.append(span);\n\n ripple(menuTab);\n\n this.tabsMenu.append(menuTab);\n\n this.mediaTabsMap.set(mediaTab.type, mediaTab);\n\n mediaTab.menuTab = menuTab;\n }\n\n this.tabsContainer = document.createElement('div');\n this.tabsContainer.classList.add('search-super-tabs-container', 'tabs-container');\n\n for(const mediaTab of this.mediaTabs) {\n const container = document.createElement('div');\n container.classList.add('search-super-container-' + mediaTab.type);\n\n const content = document.createElement('div');\n content.classList.add('search-super-content-' + mediaTab.type);\n\n container.append(content);\n\n this.tabsContainer.append(container);\n\n this.tabs[mediaTab.inputFilter] = content;\n\n mediaTab.contentTab = content;\n }\n\n this.container.append(navScrollableContainer, this.tabsContainer);\n\n // * construct end\n\n this.searchGroupMedia = new SearchGroup('', 'messages', true);\n\n this.scrollable.onScrolledBottom = () => {\n if(this.mediaTab.contentTab && this.mediaTab.contentTab.childElementCount/* && false */) {\n //this.log('onScrolledBottom will load media');\n this.load(true);\n }\n };\n //this.scroll.attachSentinels(undefined, 400);\n\n this.selectTab = horizontalMenu(this.tabsMenu, this.tabsContainer, (id, tabContent, animate) => {\n if(this.prevTabId === id && !this.skipScroll) {\n this.scrollable.scrollIntoViewNew(this.container, 'start');\n return;\n }\n \n const newMediaTab = this.mediaTabs[id];\n if(this.onChangeTab) {\n this.onChangeTab(newMediaTab);\n }\n \n const fromMediaTab = this.mediaTab;\n this.mediaTab = newMediaTab;\n\n if(this.prevTabId !== -1 && animate) {\n this.onTransitionStart();\n }\n\n if(this.skipScroll) {\n this.skipScroll = false;\n } else {\n const offsetTop = this.container.offsetTop;\n let scrollTop = this.scrollable.scrollTop;\n if(scrollTop < offsetTop) {\n this.scrollable.scrollIntoViewNew(this.container, 'start');\n scrollTop = offsetTop;\n }\n \n fromMediaTab.scroll = {scrollTop: scrollTop, scrollHeight: this.scrollable.scrollHeight};\n \n if(newMediaTab.scroll === undefined) {\n const rect = this.container.getBoundingClientRect();\n const rect2 = this.container.parentElement.getBoundingClientRect();\n const diff = rect.y - rect2.y;\n \n if(scrollTop > diff) {\n newMediaTab.scroll = {scrollTop: diff, scrollHeight: 0};\n }\n }\n \n if(newMediaTab.scroll) {\n const diff = fromMediaTab.scroll.scrollTop - newMediaTab.scroll.scrollTop;\n //console.log('what you gonna do', this.goingHard, diff);\n \n //this.scrollable.scrollTop = scrollTop;\n if(diff/* && diff < 0 */) {\n /* if(diff > -(fromMediaTab.contentTab.scrollHeight + this.nav.scrollHeight)) {\n fromMediaTab.contentTab.style.transform = `translateY(${diff}px)`;\n this.scrollable.scrollTop = scrollTop - diff;\n } else { */\n newMediaTab.contentTab.style.transform = `translateY(${diff}px)`;\n //}\n }\n }\n }\n \n /* if(this.prevTabId !== -1 && nav.offsetTop) {\n this.scrollable.scrollTop -= nav.offsetTop;\n } */\n\n /* this.log('setVirtualContainer', id, this.sharedMediaSelected, this.sharedMediaSelected.childElementCount);\n this.scroll.setVirtualContainer(this.sharedMediaSelected); */\n\n if(this.prevTabId !== -1 && !newMediaTab.contentTab.childElementCount) { // quick brown fix\n //this.contentContainer.classList.remove('loaded');\n this.load(true);\n }\n\n this.prevTabId = id;\n }, () => {\n this.scrollable.onScroll();\n \n //console.log('what y', this.tabSelected.style.transform);\n if(this.mediaTab.scroll !== undefined) {\n this.mediaTab.contentTab.style.transform = '';\n this.scrollable.scrollTop = this.mediaTab.scroll.scrollTop;\n }\n\n this.onTransitionEnd();\n }, undefined, navScrollable);\n\n this.tabs.inputMessagesFilterPhotoVideo.addEventListener('click', (e) => {\n const target = findUpClassName(e.target as HTMLDivElement, 'grid-item');\n \n const mid = +target.dataset.mid;\n if(!mid) {\n this.log.warn('no messageId by click on target:', target);\n return;\n }\n\n const peerId = +target.dataset.peerId;\n\n const targets = (Array.from(this.tabs.inputMessagesFilterPhotoVideo.querySelectorAll('.grid-item')) as HTMLElement[]).map(el => {\n return {element: el, mid: +el.dataset.mid, peerId: +el.dataset.peerId};\n });\n\n //const ids = Object.keys(this.mediaDivsByIds).map(k => +k).sort((a, b) => a - b);\n const idx = targets.findIndex(item => item.mid === mid && item.peerId === peerId);\n \n const message = appMessagesManager.getMessageByPeer(peerId, mid);\n new AppMediaViewer()\n .setSearchContext(this.copySearchContext(this.mediaTab.inputFilter))\n .openMedia(message, target, 0, false, targets.slice(0, idx), targets.slice(idx + 1));\n });\n\n this.mediaTab = this.mediaTabs[0];\n\n useHeavyAnimationCheck(() => {\n this.lazyLoadQueue.lock();\n }, () => {\n this.lazyLoadQueue.unlockAndRefresh(); // ! maybe not so efficient\n });\n }\n\n private onTransitionStart = () => {\n // Jolly Cobra's // Workaround for scrollable content flickering during animation.\n const container = this.scrollable.container;\n if(container.style.overflowY !== 'hidden') {\n // const scrollBarWidth = container.offsetWidth - container.clientWidth;\n container.style.overflowY = 'hidden';\n // container.style.paddingRight = `${scrollBarWidth}px`;\n this.container.classList.add('sliding');\n }\n };\n\n private onTransitionEnd = () => {\n // Jolly Cobra's // Workaround for scrollable content flickering during animation.\n const container = this.scrollable.container;\n\n if(isSafari) { // ! safari doesn't respect sticky header, so it flicks when overflow is changing\n container.style.display = 'none';\n }\n\n container.style.overflowY = '';\n\n if(isSafari) {\n void container.offsetLeft; // reflow\n container.style.display = '';\n }\n\n // container.style.paddingRight = '0';\n this.container.classList.remove('sliding');\n };\n\n public filterMessagesByType(messages: any[], type: SearchSuperType): MyMessage[] {\n if(type === 'inputMessagesFilterEmpty') return messages;\n\n if(type !== 'inputMessagesFilterUrl') {\n messages = messages.filter(message => !!message.media);\n }\n\n /* if(!this.peerId) {\n messages = messages.filter(message => {\n if(message.peerId === rootScope.myId) {\n return true;\n }\n\n const dialog = appMessagesManager.getDialogByPeerId(message.fromId)[0];\n return dialog && dialog.folder_id === 0;\n });\n } */\n\n let filtered: any[] = [];\n\n switch(type) {\n case 'inputMessagesFilterPhotoVideo': {\n for(let message of messages) {\n let media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);\n if(!media) {\n //this.log('no media!', message);\n continue;\n }\n \n if(media._ === 'document' && media.type !== 'video'/* && media.type !== 'gif' */) {\n //this.log('broken video', media);\n continue;\n }\n\n filtered.push(message);\n }\n \n break;\n }\n\n case 'inputMessagesFilterDocument': {\n for(let message of messages) {\n if(!message.media.document || ['voice', 'audio', 'gif', 'sticker', 'round'].includes(message.media.document.type)) {\n continue;\n }\n \n filtered.push(message);\n }\n break;\n }\n\n case 'inputMessagesFilterUrl': {\n //this.log('inputMessagesFilterUrl', messages);\n for(let message of messages) {\n //if((message.media.webpage && message.media.webpage._ !== 'webPageEmpty')) {\n filtered.push(message);\n //}\n }\n \n break;\n }\n\n case 'inputMessagesFilterMusic': {\n for(let message of messages) {\n if(!message.media.document || message.media.document.type !== 'audio') {\n continue;\n }\n\n filtered.push(message);\n }\n\n break;\n }\n\n case 'inputMessagesFilterVoice': {\n for(let message of messages) {\n if(!message.media.document || message.media.document.type !== 'voice') {\n continue;\n }\n\n filtered.push(message);\n }\n\n break;\n }\n\n default:\n break;\n }\n\n return filtered;\n }\n \n public async performSearchResult(messages: any[], mediaTab: SearchSuperMediaTab, append = true) {\n const elemsToAppend: {element: HTMLElement, message: any}[] = [];\n const sharedMediaDiv: HTMLElement = mediaTab.contentTab;\n const promises: Promise<any>[] = [];\n const middleware = this.middleware.get();\n let inputFilter = mediaTab.inputFilter;\n\n await getHeavyAnimationPromise();\n \n let searchGroup: SearchGroup;\n if(inputFilter === 'inputMessagesFilterPhotoVideo' && !!this.searchContext.query.trim()) {\n inputFilter = 'inputMessagesFilterEmpty';\n searchGroup = this.searchGroupMedia;\n sharedMediaDiv.append(searchGroup.container);\n } else if(inputFilter === 'inputMessagesFilterEmpty') {\n searchGroup = this.searchGroups.messages;\n }\n\n // https://core.telegram.org/type/MessagesFilter\n switch(inputFilter) {\n case 'inputMessagesFilterEmpty': {\n for(const message of messages) {\n const {dialog, dom} = appDialogsManager.addDialogNew({\n dialog: message.peerId, \n container: searchGroup.list, \n drawStatus: false,\n avatarSize: 54\n });\n appDialogsManager.setLastMessage(dialog, message, dom, this.searchContext.query);\n }\n\n if(searchGroup.list.childElementCount) {\n searchGroup.setActive();\n }\n break;\n }\n\n case 'inputMessagesFilterPhotoVideo': {\n for(const message of messages) {\n const media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);\n\n const div = document.createElement('div');\n div.classList.add('grid-item');\n //this.log(message, photo);\n\n let wrapped: ReturnType<typeof wrapPhoto>;\n if(media._ !== 'photo') {\n wrapped = wrapVideo({\n doc: media,\n message,\n container: div,\n boxWidth: 0,\n boxHeight: 0,\n lazyLoadQueue: this.lazyLoadQueue,\n middleware,\n onlyPreview: true,\n withoutPreloader: true,\n noPlayButton: true\n }).thumb;\n } else {\n wrapped = wrapPhoto({\n photo: media,\n message,\n container: div,\n boxWidth: 0,\n boxHeight: 0,\n lazyLoadQueue: this.lazyLoadQueue,\n middleware,\n withoutPreloader: true,\n noBlur: true\n });\n }\n\n [wrapped.images.thumb, wrapped.images.full].filter(Boolean).forEach(image => {\n image.classList.add('grid-item-media');\n });\n\n promises.push(wrapped.loadPromises.thumb);\n\n elemsToAppend.push({element: div, message});\n }\n \n break;\n }\n \n case 'inputMessagesFilterVoice':\n case 'inputMessagesFilterMusic':\n case 'inputMessagesFilterDocument': {\n for(const message of messages) {\n const showSender = this.showSender || message.media.document.type === 'voice';\n const div = wrapDocument({\n message,\n withTime: !showSender,\n fontWeight: 400,\n voiceAsMusic: true,\n showSender: showSender,\n searchContext: this.copySearchContext(inputFilter)\n });\n\n if(['audio', 'voice'].includes(message.media.document.type)) {\n div.classList.add('audio-48');\n }\n\n elemsToAppend.push({element: div, message});\n }\n break;\n }\n \n case 'inputMessagesFilterUrl': {\n for(let message of messages) {\n let webpage: any;\n\n if(message.media?.webpage && message.media.webpage._ !== 'webPageEmpty') {\n webpage = message.media.webpage;\n } else {\n const entity = message.totalEntities ? message.totalEntities.find((e: any) => e._ === 'messageEntityUrl' || e._ === 'messageEntityTextUrl') : null;\n let url: string, display_url: string, sliced: string;\n\n if(!entity) {\n //this.log.error('NO ENTITY:', message);\n const match = RichTextProcessor.matchUrl(message.message);\n if(!match) {\n //this.log.error('NO ENTITY AND NO MATCH:', message);\n continue;\n }\n\n url = match[0];\n } else {\n sliced = message.message.slice(entity.offset, entity.offset + entity.length);\n }\n\n if(entity?._ === 'messageEntityTextUrl') {\n url = entity.url;\n //display_url = sliced;\n } else {\n url = url || sliced;\n }\n\n display_url = url;\n\n const same = message.message === url;\n if(!url.match(/^(ftp|http|https):\\/\\//)) {\n display_url = 'https://' + url;\n url = url.includes('@') ? url : 'https://' + url;\n }\n\n display_url = new URL(display_url).hostname;\n\n webpage = {\n url,\n display_url\n };\n\n if(!same) {\n webpage.description = message.message;\n webpage.rDescription = RichTextProcessor.wrapRichText(limitSymbols(message.message, 150, 180));\n }\n }\n\n let div = document.createElement('div');\n \n let previewDiv = document.createElement('div');\n previewDiv.classList.add('preview');\n \n //this.log('wrapping webpage', webpage);\n \n if(webpage.photo) {\n const res = wrapPhoto({\n container: previewDiv,\n message: null,\n photo: webpage.photo,\n boxWidth: 0,\n boxHeight: 0,\n withoutPreloader: true,\n lazyLoadQueue: this.lazyLoadQueue,\n middleware,\n size: appPhotosManager.choosePhotoSize(webpage.photo, 60, 60, false),\n loadPromises: promises,\n noBlur: true\n });\n } else {\n previewDiv.classList.add('empty');\n previewDiv.innerHTML = RichTextProcessor.getAbbreviation(webpage.title || webpage.display_url || webpage.description || webpage.url, true);\n }\n \n let title = webpage.rTitle || '';\n let subtitle = webpage.rDescription || '';\n let url = RichTextProcessor.wrapRichText(webpage.url || '');\n \n if(!title) {\n //title = new URL(webpage.url).hostname;\n title = RichTextProcessor.wrapPlainText(webpage.display_url.split('/', 1)[0]);\n }\n\n let sender = this.showSender ? `<div class=\"subtitle sender\">${appMessagesManager.getSenderToPeerText(message)}</div>` : '';\n\n let titleAdditionHTML = '';\n if(this.showSender) {\n titleAdditionHTML = `<div class=\"sent-time\">${formatDateAccordingToToday(new Date(message.date * 1000))}</div>`;\n }\n\n div.append(previewDiv);\n div.insertAdjacentHTML('beforeend', `\n <div class=\"title\">${title}${titleAdditionHTML}</div>\n <div class=\"subtitle\">${subtitle}</div>\n <div class=\"url\">${url}</div>\n ${sender}\n `);\n \n if(div.innerText.trim().length) {\n elemsToAppend.push({element: div, message});\n }\n \n }\n \n break;\n }\n\n default:\n //this.log.warn('death is my friend', messages);\n break;\n }\n\n if(this.loadMutex) {\n promises.push(this.loadMutex);\n }\n\n if(promises.length) {\n await Promise.all(promises);\n if(!middleware()) {\n //this.log.warn('peer changed');\n return;\n }\n }\n \n if(elemsToAppend.length) {\n const method = append ? 'append' : 'prepend';\n elemsToAppend.forEach(details => {\n const {element, message} = details;\n const monthContainer = this.getMonthContainerByTimestamp(this.groupByMonth ? message.date : 0, inputFilter);\n element.classList.add('search-super-item');\n element.dataset.mid = '' + message.mid;\n element.dataset.peerId = '' + message.peerId;\n monthContainer.items[method](element);\n });\n }\n \n //if(type !== 'inputMessagesFilterEmpty') {\n this.afterPerforming(inputFilter === 'inputMessagesFilterEmpty' ? 1 : messages.length, sharedMediaDiv);\n //}\n }\n\n private afterPerforming(length: number, contentTab: HTMLElement) {\n if(contentTab) {\n const parent = contentTab.parentElement;\n Array.from(parent.children).slice(1).forEach(child => {\n child.remove();\n });\n\n //this.contentContainer.classList.add('loaded');\n\n if(!length && !contentTab.childElementCount) {\n const div = document.createElement('div');\n div.innerText = 'Nothing interesting here yet...';\n div.classList.add('position-center', 'text-center', 'content-empty', 'no-select');\n\n parent.append(div);\n }\n }\n }\n\n private loadChats() {\n const renderedPeerIds: Set<number> = new Set();\n const middleware = this.middleware.get();\n\n for(let i in this.searchGroups) {\n const group = this.searchGroups[i as SearchGroupType];\n this.tabs.inputMessagesFilterEmpty.append(group.container);\n group.clear();\n }\n\n const query = this.searchContext.query;\n if(query) {\n const setResults = (results: number[], group: SearchGroup, showMembersCount = false) => {\n results.forEach((peerId) => {\n if(renderedPeerIds.has(peerId)) {\n return;\n }\n \n renderedPeerIds.add(peerId);\n \n const peer = appPeersManager.getPeer(peerId);\n \n //////////this.log('contacts peer', peer);\n \n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId, \n container: group.list, \n drawStatus: false,\n avatarSize: 48,\n autonomous: group.autonomous\n });\n \n if(showMembersCount && (peer.participants_count || peer.participants)) {\n const regExp = new RegExp(`(${escapeRegExp(query)}|${escapeRegExp(searchIndexManager.cleanSearchText(query))})`, 'gi');\n dom.titleSpan.innerHTML = dom.titleSpan.innerHTML.replace(regExp, '<i>$1</i>');\n dom.lastMessageSpan.append(appChatsManager.getChatMembersString(-peerId));\n } else if(peerId === rootScope.myId) {\n dom.lastMessageSpan.append(i18n('Presence.YourChat'));\n } else {\n let username = appPeersManager.getPeerUsername(peerId);\n if(!username) {\n const user = appUsersManager.getUser(peerId);\n if(user && user.phone) {\n username = '+' + formatPhoneNumber(user.phone).formatted;\n }\n } else {\n username = '@' + username;\n }\n \n dom.lastMessageSpan.innerHTML = '<i>' + username + '</i>';\n }\n });\n \n group.toggle();\n };\n \n const onLoad = <T>(arg: T) => {\n if(!middleware()) {\n return;\n }\n \n //this.loadedContacts = true;\n \n return arg;\n };\n \n return Promise.all([\n appUsersManager.getContacts(query, true)\n .then(onLoad)\n .then((contacts) => {\n if(contacts) {\n setResults(contacts, this.searchGroups.contacts, true);\n }\n }),\n \n appUsersManager.searchContacts(query, 20)\n .then(onLoad)\n .then((contacts) => {\n if(contacts) {\n setResults(contacts.my_results, this.searchGroups.contacts, true);\n setResults(contacts.results/* .concat(contacts.results, contacts.results, contacts.results) */, this.searchGroups.globalContacts);\n\n if(this.searchGroups.globalContacts.nameEl.lastElementChild) {\n this.searchGroups.globalContacts.nameEl.lastElementChild.remove();\n }\n\n this.searchGroups.globalContacts.container.classList.add('is-short');\n \n if(this.searchGroups.globalContacts.list.childElementCount > 3) {\n const showMore = document.createElement('div');\n showMore.classList.add('search-group__show-more');\n showMore.innerText = 'Show more';\n this.searchGroups.globalContacts.nameEl.append(showMore);\n showMore.addEventListener('click', () => {\n const isShort = this.searchGroups.globalContacts.container.classList.toggle('is-short');\n showMore.innerText = isShort ? 'Show more' : 'Show less';\n });\n }\n }\n }),\n \n appMessagesManager.getConversations(query, 0, 20, 0)\n .then(onLoad)\n .then(value => {\n if(value) {\n setResults(value.dialogs.map(d => d.peerId), this.searchGroups.contacts, true);\n }\n })\n ]);\n } else if(!this.searchContext.peerId && !this.searchContext.minDate) {\n const renderRecentSearch = (setActive = true) => {\n return appStateManager.getState().then(state => {\n if(!middleware()) {\n return;\n }\n \n this.searchGroups.recent.list.innerHTML = '';\n \n state.recentSearch.slice(0, 20).forEach(peerId => {\n let {dialog, dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: this.searchGroups.recent.list,\n drawStatus: false,\n meAsSaved: true,\n avatarSize: 48,\n autonomous: true\n });\n \n dom.lastMessageSpan.append(peerId > 0 ? appUsersManager.getUserStatusString(peerId) : appChatsManager.getChatMembersString(peerId));\n });\n \n if(!state.recentSearch.length) {\n this.searchGroups.recent.clear();\n } else if(setActive) {\n this.searchGroups.recent.setActive();\n }\n });\n };\n\n return Promise.all([\n appUsersManager.getTopPeers().then(peers => {\n if(!middleware()) return;\n\n //console.log('got top categories:', categories);\n if(peers.length) {\n peers.forEach((peerId) => {\n appDialogsManager.addDialogNew({\n dialog: peerId, \n container: this.searchGroups.people.list, \n drawStatus: false,\n onlyFirstName: true,\n avatarSize: 54,\n autonomous: false\n });\n });\n }\n \n this.searchGroups.people.setActive();\n }),\n\n renderRecentSearch()\n ]);\n } else return Promise.resolve();\n }\n\n private loadMembers(mediaTab: SearchSuperMediaTab) {\n const id = -this.searchContext.peerId;\n const middleware = this.middleware.get();\n let promise: Promise<void>;\n\n const renderParticipants = async(participants: (ChatParticipant | ChannelParticipant)[]) => {\n if(this.loadMutex) {\n await this.loadMutex;\n\n if(!middleware()) {\n return;\n }\n }\n \n if(!this.membersList) {\n this.membersList = new SortedUserList();\n this.membersList.list.addEventListener('click', (e) => {\n const li = findUpTag(e.target, 'LI');\n if(!li) {\n return;\n }\n\n const peerId = +li.dataset.peerId;\n let promise: Promise<any> = Promise.resolve();\n if(mediaSizes.isMobile) {\n promise = appSidebarRight.toggleSidebar(false);\n }\n \n promise.then(() => {\n appImManager.setInnerPeer(peerId);\n });\n });\n mediaTab.contentTab.append(this.membersList.list);\n this.afterPerforming(1, mediaTab.contentTab);\n }\n\n participants.forEach(participant => {\n const user = appUsersManager.getUser(participant.user_id);\n if(user.pFlags.deleted) {\n return;\n }\n\n this.membersList.add(participant.user_id);\n });\n };\n\n if(appChatsManager.isChannel(id)) {\n const LOAD_COUNT = !this.membersList ? 50 : 200;\n promise = appProfileManager.getChannelParticipants(id, undefined, LOAD_COUNT, this.nextRates[mediaTab.inputFilter]).then(participants => {\n if(!middleware()) {\n return;\n }\n\n let list = mediaTab.contentTab.firstElementChild as HTMLUListElement;\n this.nextRates[mediaTab.inputFilter] = (list ? list.childElementCount : 0) + participants.participants.length;\n\n if(participants.participants.length < LOAD_COUNT) {\n this.loaded[mediaTab.inputFilter] = true;\n }\n\n return renderParticipants(participants.participants);\n });\n } else {\n promise = (appProfileManager.getChatFull(id) as Promise<ChatFull.chatFull>).then(chatFull => {\n if(!middleware()) {\n return;\n }\n\n //console.log('anymore', chatFull);\n this.loaded[mediaTab.inputFilter] = true;\n const participants = chatFull.participants;\n if(participants._ === 'chatParticipantsForbidden') {\n return;\n }\n \n return renderParticipants(participants.participants);\n });\n }\n\n return this.loadPromises[mediaTab.inputFilter] = promise.finally(() => { \n if(!middleware()) {\n return;\n }\n\n this.loadPromises[mediaTab.inputFilter] = null;\n });\n }\n\n private loadType(mediaTab: SearchSuperMediaTab, justLoad: boolean, loadCount: number, middleware: () => boolean) {\n const type = mediaTab.inputFilter;\n\n if(this.loadPromises[type]) {\n return this.loadPromises[type];\n }\n\n if(mediaTab.type === 'members') {\n return this.loadMembers(mediaTab);\n }\n\n const history = this.historyStorage[type] ?? (this.historyStorage[type] = []);\n\n if(type === 'inputMessagesFilterEmpty' && !history.length) {\n if(!this.loadedChats) {\n this.loadChats();\n this.loadedChats = true;\n }\n\n if(!this.searchContext.query.trim() && !this.searchContext.peerId && !this.searchContext.minDate) {\n this.loaded[type] = true;\n return Promise.resolve();\n }\n }\n\n const logStr = 'load [' + type + ']: ';\n\n // render from cache\n if(history.length && this.usedFromHistory[type] < history.length && !justLoad) {\n let messages: any[] = [];\n let used = Math.max(0, this.usedFromHistory[type]);\n let slicedLength = 0;\n\n do {\n let ids = history.slice(used, used + loadCount);\n //this.log(logStr + 'will render from cache', used, history, ids, loadCount);\n used += ids.length;\n slicedLength += ids.length;\n\n messages.push(...this.filterMessagesByType(ids.map(m => appMessagesManager.getMessageByPeer(m.peerId, m.mid)), type));\n } while(slicedLength < loadCount && used < history.length);\n \n // если перебор\n /* if(slicedLength > loadCount) {\n let diff = messages.length - loadCount;\n messages = messages.slice(0, messages.length - diff);\n used -= diff;\n } */\n\n this.usedFromHistory[type] = used;\n //if(messages.length) {\n return this.performSearchResult(messages, mediaTab).finally(() => {\n setTimeout(() => {\n this.scrollable.checkForTriggers();\n }, 0);\n });\n //}\n\n return Promise.resolve();\n }\n \n let maxId = history.length ? history[history.length - 1].mid : 0;\n \n //this.log(logStr + 'search house of glass pre', type, maxId);\n \n //let loadCount = history.length ? 50 : 15;\n return this.loadPromises[type] = appMessagesManager.getSearch({\n peerId: this.searchContext.peerId, \n query: this.searchContext.query,\n inputFilter: {_: type},\n maxId, \n limit: loadCount,\n nextRate: this.nextRates[type] ?? (this.nextRates[type] = 0),\n threadId: this.searchContext.threadId,\n folderId: this.searchContext.folderId,\n minDate: this.searchContext.minDate,\n maxDate: this.searchContext.maxDate\n }).then(value => {\n history.push(...value.history.map(m => ({mid: m.mid, peerId: m.peerId})));\n \n this.log(logStr + 'search house of glass', type, value);\n\n if(!middleware()) {\n //this.log.warn('peer changed');\n return;\n }\n\n // ! Фикс случая, когда не загружаются документы при открытой панели разработчиков (происходит из-за того, что не совпадают критерии отбора документов в getSearch)\n if(value.history.length < loadCount) {\n //if((value.count || history.length === value.count) && history.length >= value.count) {\n //this.log(logStr + 'loaded all media', value, loadCount);\n this.loaded[type] = true;\n }\n\n this.nextRates[type] = value.next_rate;\n\n if(justLoad) {\n return Promise.resolve();\n }\n\n this.usedFromHistory[type] = history.length;\n\n if(!this.loaded[type]) {\n (this.loadPromises[type] || Promise.resolve()).then(() => {\n setTimeout(() => {\n if(!middleware()) return;\n //this.log('will preload more');\n if(this.mediaTab === mediaTab) {\n const promise = this.load(true, true);\n if(promise) {\n promise.then(() => {\n if(!middleware()) return;\n //this.log('preloaded more');\n setTimeout(() => {\n this.scrollable.checkForTriggers();\n }, 0);\n });\n }\n }\n }, 0);\n });\n }\n\n //if(value.history.length) {\n return this.performSearchResult(this.filterMessagesByType(value.history, type), mediaTab);\n //}\n }).catch(err => {\n this.log.error('load error:', err);\n }).finally(() => {\n this.loadPromises[type] = null;\n });\n }\n \n public async load(single = false, justLoad = false) {\n // if(testScroll/* || 1 === 1 */) {\n // return;\n // }\n\n //return;\n \n const peerId = this.searchContext.peerId;\n this.log('load', single, peerId, this.loadPromises);\n const middleware = this.middleware.get();\n\n if(this.firstLoad) {\n if(this.hideEmptyTabs) {\n const mediaTabs = this.mediaTabs.filter(mediaTab => mediaTab.inputFilter !== 'inputMessagesFilterEmpty')\n const filters = mediaTabs.map(mediaTab => ({_: mediaTab.inputFilter}));\n\n const counters = await appMessagesManager.getSearchCounters(peerId, filters);\n if(!middleware()) {\n return;\n }\n\n if(this.loadMutex) {\n await this.loadMutex;\n\n if(!middleware()) {\n return;\n }\n }\n\n let firstMediaTab: SearchSuperMediaTab;\n let count = 0;\n mediaTabs.forEach(mediaTab => {\n const counter = counters.find(c => c.filter._ === mediaTab.inputFilter);\n\n mediaTab.menuTab.classList.toggle('hide', !counter.count);\n mediaTab.menuTab.classList.remove('active');\n //mediaTab.contentTab.classList.toggle('hide', !counter.count);\n\n if(counter.count && firstMediaTab === undefined) {\n firstMediaTab = mediaTab;\n }\n\n if(counter.count) ++count;\n });\n\n const membersTab = this.mediaTabsMap.get('members');\n const canViewMembers = this.canViewMembers();\n membersTab.menuTab.classList.toggle('hide', !canViewMembers);\n\n if(canViewMembers) {\n firstMediaTab = membersTab;\n }\n\n this.container.classList.toggle('hide', !firstMediaTab);\n this.container.parentElement.classList.toggle('search-empty', !firstMediaTab);\n if(firstMediaTab) {\n this.skipScroll = true;\n this.selectTab(this.mediaTabs.indexOf(firstMediaTab), false);\n firstMediaTab.menuTab.classList.add('active');\n\n this.navScrollableContainer.classList.toggle('hide', count <= 1);\n }\n }\n\n this.firstLoad = false;\n }\n \n let toLoad = single ? [this.mediaTab] : this.mediaTabs.filter(t => t !== this.mediaTab);\n toLoad = toLoad.filter(mediaTab => {\n const inputFilter = mediaTab.inputFilter;\n return !this.loaded[inputFilter] || (this.historyStorage[inputFilter] && this.usedFromHistory[inputFilter] < this.historyStorage[inputFilter].length);\n });\n\n if(!toLoad.length) {\n return;\n }\n\n const loadCount = justLoad ? 50 : Math.round((appPhotosManager.windowH / 130 | 0) * 3 * 1.25); // that's good for all types\n\n const promises: Promise<any>[] = toLoad.map(mediaTab => {\n return this.loadType(mediaTab, justLoad, loadCount, middleware)\n });\n\n return Promise.all(promises).catch(err => {\n this.log.error('Load error all promises:', err);\n });\n }\n \n public getMonthContainerByTimestamp(timestamp: number, type: SearchSuperType) {\n const date = new Date(timestamp * 1000);\n date.setHours(0, 0, 0);\n date.setDate(1);\n const dateTimestamp = date.getTime();\n const containers = this.monthContainers[type] ?? (this.monthContainers[type] = {});\n if(!(dateTimestamp in containers)) {\n const str = months[date.getMonth()] + ' ' + date.getFullYear();\n \n const container = document.createElement('div');\n container.className = 'search-super-month';\n\n const name = document.createElement('div');\n name.classList.add('search-super-month-name');\n name.innerText = str;\n container.append(name);\n\n const items = document.createElement('div');\n items.classList.add('search-super-month-items');\n\n container.append(name, items);\n\n const haveTimestamps = getObjectKeysAndSort(containers, 'desc');\n let i = 0;\n for(; i < haveTimestamps.length; ++i) {\n const t = haveTimestamps[i];\n if(dateTimestamp > t) {\n break;\n }\n }\n \n containers[dateTimestamp] = {container, items};\n positionElementByIndex(container, this.tabs[type], i);\n }\n\n return containers[dateTimestamp];\n }\n\n public canViewMembers() {\n return this.searchContext.peerId < 0 && !appChatsManager.isBroadcast(-this.searchContext.peerId) && appChatsManager.hasRights(-this.searchContext.peerId, 'view_participants');\n }\n\n public cleanup() {\n this.loadPromises = {};\n this.loaded = {};\n this.loadedChats = false;\n this.nextRates = {};\n this.firstLoad = true;\n\n this.lazyLoadQueue.clear();\n\n this.mediaTabs.forEach(mediaTab => {\n this.usedFromHistory[mediaTab.inputFilter] = -1;\n });\n\n // * must go to first tab (это костыль)\n /* const membersTab = this.mediaTabsMap.get('members');\n if(membersTab) {\n const tab = this.canViewMembers() ? membersTab : this.mediaTabs[this.mediaTabs.indexOf(membersTab) + 1];\n this.mediaTab = tab;\n } */\n\n this.middleware.clean();\n this.cleanScrollPositions();\n this.membersList = undefined;\n }\n\n public cleanScrollPositions() {\n this.mediaTabs.forEach(mediaTab => {\n mediaTab.scroll = undefined;\n });\n }\n\n public cleanupHTML(goFirst = false) {\n if(this.urlsToRevoke.length) {\n this.urlsToRevoke.forEach(url => {\n URL.revokeObjectURL(url);\n });\n this.urlsToRevoke.length = 0;\n }\n\n this.mediaTabs.forEach((tab) => {\n tab.contentTab.innerHTML = '';\n\n if(this.hideEmptyTabs) {\n //tab.menuTab.classList.add('hide');\n this.container.classList.add('hide');\n this.container.parentElement.classList.add('search-empty');\n }\n\n if(tab.type === 'chats') {\n return;\n }\n \n if(!this.historyStorage[tab.inputFilter]) {\n const parent = tab.contentTab.parentElement;\n //if(!testScroll) {\n if(!parent.querySelector('.preloader')) {\n putPreloader(parent, true);\n }\n //}\n\n const empty = parent.querySelector('.content-empty');\n if(empty) {\n empty.remove();\n }\n }\n });\n\n /* if(goFirst) {\n const membersTab = this.mediaTabsMap.get('members');\n if(membersTab) {\n let idx = this.canViewMembers() ? 0 : 1;\n membersTab.menuTab.classList.toggle('hide', idx !== 0);\n\n this.selectTab(idx, false);\n } else {\n this.selectTab(0, false);\n }\n } */\n\n this.monthContainers = {};\n this.searchGroupMedia.clear();\n this.scrollable.scrollTop = 0;\n\n /* if(testScroll) {\n for(let i = 0; i < 1500; ++i) {\n let div = document.createElement('div');\n div.insertAdjacentHTML('beforeend', `<img class=\"media-image\" src=\"assets/img/camomile.jpg\">`);\n div.classList.add('grid-item');\n div.dataset.id = '' + (i / 3 | 0);\n //div.innerText = '' + (i / 3 | 0);\n this.tabs.inputMessagesFilterPhotoVideo.append(div);\n }\n } */\n }\n\n private copySearchContext(newInputFilter: MyInputMessagesFilter) {\n const context = copy(this.searchContext);\n context.inputFilter = newInputFilter;\n context.nextRate = this.nextRates[newInputFilter];\n return context;\n }\n\n public setQuery({peerId, query, threadId, historyStorage, folderId, minDate, maxDate}: {\n peerId: number, \n query?: string, \n threadId?: number, \n historyStorage?: AppSearchSuper['historyStorage'], \n folderId?: number,\n minDate?: number,\n maxDate?: number\n }) {\n this.searchContext = {\n peerId: peerId || 0,\n query: query || '',\n inputFilter: this.mediaTab.inputFilter,\n threadId,\n folderId,\n minDate,\n maxDate\n };\n \n this.historyStorage = historyStorage ?? {};\n\n this.cleanup();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { attachClickEvent, AttachClickOptions, cancelEvent, CLICK_EVENT_NAME } from \"../helpers/dom\";\nimport ListenerSetter from \"../helpers/listenerSetter\";\nimport { i18n, LangPackKey } from \"../lib/langPack\";\nimport CheckboxField from \"./checkboxField\";\nimport { closeBtnMenu } from \"./misc\";\nimport { ripple } from \"./ripple\";\n\nexport type ButtonMenuItemOptions = {\n icon: string, \n text: LangPackKey, \n onClick: (e: MouseEvent | TouchEvent) => void, \n element?: HTMLElement,\n options?: AttachClickOptions,\n checkboxField?: CheckboxField,\n /* , cancelEvent?: true */\n};\n\nconst ButtonMenuItem = (options: ButtonMenuItemOptions) => {\n if(options.element) return options.element;\n\n const {icon, text, onClick} = options;\n const el = document.createElement('div');\n el.className = 'btn-menu-item tgico-' + icon;\n ripple(el);\n const t = i18n(text);\n t.classList.add('btn-menu-item-text');\n el.append(t);\n\n if(options.checkboxField) {\n el.append(options.checkboxField.label);\n attachClickEvent(el, () => {\n options.checkboxField.checked = !options.checkboxField.checked;\n }, options.options);\n }\n\n // * cancel keyboard close\n attachClickEvent(el, CLICK_EVENT_NAME !== 'click' ? (e) => {\n cancelEvent(e);\n onClick(e);\n closeBtnMenu();\n } : onClick, options.options);\n\n return options.element = el;\n};\n\nconst ButtonMenu = (buttons: ButtonMenuItemOptions[], listenerSetter?: ListenerSetter) => {\n const el = document.createElement('div');\n el.classList.add('btn-menu');\n\n if(listenerSetter) {\n buttons.forEach(b => {\n if(b.options) {\n b.options.listenerSetter = listenerSetter;\n } else {\n b.options = {listenerSetter};\n }\n });\n }\n\n const items = buttons.map(ButtonMenuItem);\n\n el.append(...items);\n\n return el;\n};\n\nexport default ButtonMenu;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { AttachClickOptions, cancelEvent, CLICK_EVENT_NAME } from \"../helpers/dom\";\nimport ListenerSetter from \"../helpers/listenerSetter\";\nimport ButtonIcon from \"./buttonIcon\";\nimport ButtonMenu, { ButtonMenuItemOptions } from \"./buttonMenu\";\nimport { closeBtnMenu, openBtnMenu } from \"./misc\";\n\nconst ButtonMenuToggle = (options: Partial<{noRipple: true, onlyMobile: true, listenerSetter: ListenerSetter, asDiv: boolean}> = {}, direction: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right', buttons: ButtonMenuItemOptions[], onOpen?: (e: Event) => void) => {\n options.asDiv = true;\n const button = ButtonIcon('more btn-menu-toggle', options);\n\n const btnMenu = ButtonMenu(buttons, options.listenerSetter);\n btnMenu.classList.add(direction);\n ButtonMenuToggleHandler(button, onOpen, options);\n button.append(btnMenu);\n return button;\n};\n\n// TODO: refactor for attachClickEvent, because if move finger after touchstart, it will start anyway\nconst ButtonMenuToggleHandler = (el: HTMLElement, onOpen?: (e: Event) => void, options?: AttachClickOptions) => {\n const add = options?.listenerSetter ? options.listenerSetter.add.bind(options.listenerSetter, el) : el.addEventListener.bind(el);\n\n //console.trace('ButtonMenuToggleHandler attach', el, onOpen, options);\n add(CLICK_EVENT_NAME, (e: Event) => {\n //console.log('ButtonMenuToggleHandler click', e);\n if(!el.classList.contains('btn-menu-toggle')) return false;\n\n //window.removeEventListener('mousemove', onMouseMove);\n const openedMenu = el.querySelector('.btn-menu') as HTMLDivElement;\n cancelEvent(e);\n\n if(el.classList.contains('menu-open')) {\n closeBtnMenu();\n } else {\n onOpen && onOpen(e);\n openBtnMenu(openedMenu);\n }\n });\n};\n\nexport { ButtonMenuToggleHandler };\nexport default ButtonMenuToggle;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport { InputPrivacyKey, InputPrivacyRule, PrivacyRule, Update, PrivacyKey } from \"../../layer\";\nimport apiManager from \"../mtproto/mtprotoworker\";\nimport appChatsManager from \"./appChatsManager\";\nimport appUsersManager from \"./appUsersManager\";\nimport apiUpdatesManager from \"./apiUpdatesManager\";\nimport rootScope from \"../rootScope\";\nimport { convertInputKeyToKey } from \"../../helpers/string\";\n\nexport enum PrivacyType {\n Everybody = 2,\n Contacts = 1,\n Nobody = 0\n}\n\nexport class AppPrivacyManager {\n private privacy: Partial<{\n [key in PrivacyKey['_']]: PrivacyRule[] | Promise<PrivacyRule[]>\n }> = {};\n\n constructor() {\n rootScope.on('apiUpdate', (e) => {\n const update = e as Update;\n\n switch(update._) {\n case 'updatePrivacy':\n const key = update.key._;\n this.privacy[key] = update.rules;\n rootScope.broadcast('privacy_update', update);\n break;\n }\n });\n }\n\n public setPrivacy(inputKey: InputPrivacyKey['_'], rules: InputPrivacyRule[]) {\n return apiManager.invokeApi('account.setPrivacy', {\n key: {\n _: inputKey\n },\n rules\n }).then(privacyRules => {\n appUsersManager.saveApiUsers(privacyRules.users);\n appChatsManager.saveApiChats(privacyRules.chats);\n\n apiUpdatesManager.processUpdateMessage({\n _: 'updateShort',\n update: {\n _: 'updatePrivacy',\n key: {\n _: convertInputKeyToKey(inputKey)\n },\n rules: rules.map(inputRule => {\n const rule: PrivacyRule = {} as any;\n Object.assign(rule, inputRule);\n rule._ = convertInputKeyToKey(rule._) as any;\n return rule;\n })\n } as Update.updatePrivacy\n });\n\n //console.log('privacy rules', inputKey, privacyRules, privacyRules.rules);\n\n return privacyRules.rules;\n });\n }\n\n public getPrivacy(inputKey: InputPrivacyKey['_']) {\n const privacyKey: PrivacyKey['_'] = convertInputKeyToKey(inputKey) as any;\n const rules = this.privacy[privacyKey];\n if(rules) {\n return Promise.resolve(rules);\n }\n \n return this.privacy[privacyKey] = apiManager.invokeApi('account.getPrivacy', {\n key: {\n _: inputKey\n }\n }).then(privacyRules => {\n appUsersManager.saveApiUsers(privacyRules.users);\n appChatsManager.saveApiChats(privacyRules.chats);\n\n //console.log('privacy rules', inputKey, privacyRules, privacyRules.rules);\n\n return this.privacy[privacyKey] = privacyRules.rules;\n });\n }\n\n public getPrivacyRulesDetails(rules: PrivacyRule[]) {\n const types: PrivacyType[] = [];\n\n type peers = {users: number[], chats: number[]};\n let allowPeers: peers = {users: [], chats: []}, disallowPeers: peers = {users: [], chats: []};\n rules.forEach(rule => {\n switch(rule._) {\n case 'privacyValueAllowAll':\n types.push(2);\n break;\n case 'privacyValueDisallowAll':\n types.push(0);\n break;\n case 'privacyValueAllowContacts': \n types.push(1);\n break;\n /* case 'privacyValueDisallowContacts':\n types.push('Except My Contacts');\n break; */\n case 'privacyValueAllowChatParticipants':\n allowPeers.chats.push(...rule.chats);\n break;\n case 'privacyValueAllowUsers':\n allowPeers.users.push(...rule.users);\n break;\n case 'privacyValueDisallowChatParticipants':\n disallowPeers.chats.push(...rule.chats);\n break;\n case 'privacyValueDisallowUsers':\n disallowPeers.users.push(...rule.users);\n break;\n }\n });\n\n return {type: types[0], disallowPeers, allowPeers};\n }\n}\n\nconst appPrivacyManager = new AppPrivacyManager();\nMOUNT_CLASS_TO.appPrivacyManager = appPrivacyManager;\nexport default appPrivacyManager;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { randomLong } from \"../helpers/random\";\nimport { InputPrivacyKey, InputPrivacyRule } from \"../layer\";\nimport appPrivacyManager, { PrivacyType } from \"../lib/appManagers/appPrivacyManager\";\nimport appUsersManager from \"../lib/appManagers/appUsersManager\";\nimport { i18n, join, LangPackKey, _i18n } from \"../lib/langPack\";\nimport RadioField from \"./radioField\";\nimport Row, { RadioFormFromRows } from \"./row\";\nimport Scrollable from \"./scrollable\";\nimport { SettingSection, generateSection } from \"./sidebarLeft\";\nimport AppAddMembersTab from \"./sidebarLeft/tabs/addMembers\";\nimport { SliderSuperTabEventable } from \"./sliderTab\";\n\ntype PrivacySectionStr = LangPackKey | '';\nexport default class PrivacySection {\n public radioRows: Map<PrivacyType, Row>;\n public radioSection: SettingSection;\n public exceptions: Map<keyof PrivacySection['peerIds'], {\n titleLangKey: LangPackKey,\n key: keyof PrivacySection['peerIds'],\n row: Row,\n icon: string,\n subtitleLangKey: LangPackKey,\n clickable: true\n }>;\n public peerIds: {\n disallow?: number[],\n allow?: number[]\n };\n public type: PrivacyType;\n\n constructor(public options: {\n tab: SliderSuperTabEventable,\n title: LangPackKey, \n inputKey: InputPrivacyKey['_'], \n captions?: [PrivacySectionStr, PrivacySectionStr, PrivacySectionStr],\n appendTo?: Scrollable,\n noExceptions?: boolean,\n onRadioChange?: (value: number) => any,\n skipTypes?: PrivacyType[],\n exceptionTexts?: [LangPackKey, LangPackKey]\n }) {\n if(options.captions) {\n options.captions.reverse();\n }\n\n this.radioSection = new SettingSection({name: options.title, caption: true});\n\n this.radioRows = new Map();\n\n let r: Array<{type: PrivacyType, langKey: LangPackKey}> = [{\n type: PrivacyType.Everybody,\n langKey: 'PrivacySettingsController.Everbody'\n }, {\n type: PrivacyType.Contacts,\n langKey: 'PrivacySettingsController.MyContacts'\n }, {\n type: PrivacyType.Nobody,\n langKey: 'PrivacySettingsController.Nobody'\n }];\n\n if(options.skipTypes) {\n r = r.filter(r => !options.skipTypes.includes(r.type));\n }\n \n const random = randomLong();\n r.forEach(({type, langKey}) => {\n const row = new Row({\n radioField: new RadioField({\n langKey, \n name: random, \n value: '' + type\n })\n });\n \n this.radioRows.set(type, row);\n });\n\n const form = RadioFormFromRows([...this.radioRows.values()], this.onRadioChange);\n\n this.radioSection.content.append(form);\n if(options.appendTo) {\n options.appendTo.append(this.radioSection.container);\n }\n\n if(!options.noExceptions) {\n const container = generateSection(options.appendTo, 'PrivacyExceptions', 'PrivacySettingsController.PeerInfo');\n\n this.exceptions = new Map([[\n 'disallow', \n {\n titleLangKey: options.exceptionTexts[0],\n key: 'disallow',\n row: null,\n icon: 'deleteuser',\n subtitleLangKey: 'PrivacySettingsController.AddUsers',\n clickable: true\n }\n ], [\n 'allow', \n {\n titleLangKey: options.exceptionTexts[1],\n key: 'allow',\n row: null,\n icon: 'adduser',\n subtitleLangKey: 'PrivacySettingsController.AddUsers',\n clickable: true\n }\n ]]);\n\n this.exceptions.forEach((exception) => {\n exception.row = new Row(exception);\n\n exception.row.container.addEventListener('click', () => {\n promise.then(() => {\n const _peerIds = this.peerIds[exception.key];\n new AppAddMembersTab(options.tab.slider).open({\n type: 'privacy',\n skippable: true,\n title: exception.titleLangKey,\n placeholder: 'PrivacyModal.Search.Placeholder',\n takeOut: (newPeerIds) => {\n _peerIds.length = 0;\n _peerIds.push(...newPeerIds);\n exception.row.subtitle.innerHTML = '';\n exception.row.subtitle.append(...this.generateStr(this.splitPeersByType(newPeerIds)));\n },\n selectedPeerIds: _peerIds\n });\n });\n });\n\n container.append(exception.row.container);\n });\n }\n\n /* setTimeout(() => {\n this.setRadio(PrivacyType.Contacts);\n }, 0); */\n\n const promise = appPrivacyManager.getPrivacy(options.inputKey).then(rules => {\n const details = appPrivacyManager.getPrivacyRulesDetails(rules);\n this.setRadio(details.type);\n\n if(this.exceptions) {\n this.peerIds = {};\n (['allow', 'disallow'] as ('allow' | 'disallow')[]).forEach(k => {\n const arr = [];\n const from = k === 'allow' ? details.allowPeers : details.disallowPeers;\n arr.push(...from.users);\n arr.push(...from.chats.map(id => -id));\n this.peerIds[k] = arr;\n const s = this.exceptions.get(k).row.subtitle;\n s.innerHTML = '';\n s.append(...this.generateStr(from));\n });\n }\n\n options.tab.eventListener.addEventListener('destroy', () => {\n const rules: InputPrivacyRule[] = [];\n\n switch(this.type) {\n case PrivacyType.Everybody:\n rules.push({_: 'inputPrivacyValueAllowAll'});\n break;\n case PrivacyType.Contacts:\n rules.push({_: 'inputPrivacyValueAllowContacts'});\n break;\n case PrivacyType.Nobody:\n rules.push({_: 'inputPrivacyValueDisallowAll'});\n break;\n }\n\n if(this.exceptions) {\n ([\n ['allow', 'inputPrivacyValueAllowChatParticipants', 'inputPrivacyValueAllowUsers'],\n ['disallow', 'inputPrivacyValueDisallowChatParticipants', 'inputPrivacyValueDisallowUsers']\n ] as Array<[\n 'allow' | 'disallow', \n 'inputPrivacyValueAllowChatParticipants' | 'inputPrivacyValueDisallowChatParticipants', \n 'inputPrivacyValueAllowUsers' | 'inputPrivacyValueDisallowUsers'\n ]>).forEach(([k, chatKey, usersKey], idx) => {\n if(this.exceptions.get(k).row.container.classList.contains('hide')) {\n return;\n }\n\n const _peerIds: number[] = this.peerIds[k];\n \n if(_peerIds) {\n const splitted = this.splitPeersByType(_peerIds);\n if(splitted.chats.length) {\n rules.push({_: chatKey, chats: splitted.chats.map(peerId => -peerId)});\n }\n \n if(splitted.users.length) {\n rules.push({_: usersKey, users: splitted.users.map(id => appUsersManager.getUserInput(id))});\n }\n }\n });\n }\n \n appPrivacyManager.setPrivacy(options.inputKey, rules);\n }, true);\n });\n }\n\n private onRadioChange = (value: string | PrivacySection['type']) => {\n value = +value as PrivacySection['type'];\n this.type = value;\n\n const caption = this.options.captions[this.type];\n const captionElement = this.radioSection.caption;\n if(!caption) {\n captionElement.innerHTML = '';\n } else {\n _i18n(captionElement, caption);\n }\n captionElement.classList.toggle('hide', !caption);\n\n if(this.exceptions) {\n this.exceptions.get('allow').row.container.classList.toggle('hide', this.type === PrivacyType.Everybody);\n this.exceptions.get('disallow').row.container.classList.toggle('hide', this.type === PrivacyType.Nobody);\n }\n\n this.options.onRadioChange && this.options.onRadioChange(value);\n };\n\n public setRadio(type: PrivacySection['type']) {\n const row = this.radioRows.get(type);\n this.onRadioChange(type);\n row.radioField.input.checked = true;\n }\n \n private splitPeersByType(peerIds: number[]) {\n const peers = {users: [] as number[], chats: [] as number[]};\n peerIds.forEach(peerId => {\n peers[peerId < 0 ? 'chats' : 'users'].push(peerId < 0 ? -peerId : peerId);\n });\n\n return peers;\n }\n\n private generateStr(peers: {users: number[], chats: number[]}): HTMLElement[] {\n if(!peers.users.length && !peers.chats.length) {\n return [i18n('PrivacySettingsController.AddUsers')];\n }\n\n return join([\n peers.users.length ? i18n('Users', [peers.users.length]) : null, \n peers.chats.length ? i18n('Chats', [peers.chats.length]) : null\n ].filter(Boolean), false);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { PrivacyType } from \"../../../../lib/appManagers/appPrivacyManager\";\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyPhoneNumberTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-phone-number');\n this.setTitle('PrivacyPhone');\n\n const phoneCaption: LangPackKey = 'PrivacyPhoneInfo';\n const phoneSection = new PrivacySection({\n tab: this,\n title: 'PrivacyPhoneTitle',\n inputKey: 'inputPrivacyKeyPhoneNumber',\n captions: [phoneCaption, phoneCaption, ''],\n exceptionTexts: ['PrivacySettingsController.NeverShare', 'PrivacySettingsController.AlwaysShare'],\n appendTo: this.scrollable,\n onRadioChange: (type) => {\n s.setRadio(PrivacyType.Everybody);\n s.radioSection.container.classList.toggle('hide', type !== PrivacyType.Nobody);\n }\n });\n\n const sCaption: LangPackKey = 'PrivacyPhoneInfo3';\n const s = new PrivacySection({\n tab: this,\n title: 'PrivacyPhoneTitle2',\n inputKey: 'inputPrivacyKeyAddedByPhone',\n captions: [sCaption, sCaption, ''],\n noExceptions: true,\n skipTypes: [PrivacyType.Nobody]\n });\n\n this.scrollable.container.insertBefore(s.radioSection.container, phoneSection.radioSection.container.nextSibling);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { Document, InputFileLocation, InputStickerSet, MessagesAllStickers, MessagesFeaturedStickers, MessagesFoundStickerSets, MessagesRecentStickers, MessagesStickers, MessagesStickerSet, PhotoSize, StickerPack, StickerSet, StickerSetCovered } from '../../layer';\nimport { Modify } from '../../types';\nimport apiManager from '../mtproto/mtprotoworker';\nimport rootScope from '../rootScope';\nimport appDocsManager from './appDocsManager';\nimport AppStorage from '../storage';\nimport { MOUNT_CLASS_TO } from '../../config/debug';\nimport { forEachReverse } from '../../helpers/array';\n\n// TODO: если пак будет сохранён и потом обновлён, то недостающие стикеры не подгрузит\n\nexport class AppStickersManager {\n private storage = new AppStorage<Record<string, MessagesStickerSet>>({\n storeName: 'stickerSets'\n });\n\n private getStickerSetPromises: {[setId: string]: Promise<MessagesStickerSet>} = {};\n private getStickersByEmoticonsPromises: {[emoticon: string]: Promise<Document[]>} = {};\n \n constructor() {\n this.getStickerSet({id: 'emoji', access_hash: ''}, {overwrite: true});\n\n rootScope.on('apiUpdate', (e) => {\n const update = e;\n \n switch(update._) {\n case 'updateNewStickerSet': {\n this.saveStickerSet(update.stickerset, update.stickerset.set.id);\n rootScope.broadcast('stickers_installed', update.stickerset.set);\n break;\n }\n }\n });\n }\n\n public saveStickers(docs: Document[]) {\n forEachReverse(docs, (doc, idx) => {\n doc = appDocsManager.saveDoc(doc);\n\n if(!doc) docs.splice(idx, 1);\n else docs[idx] = doc;\n });\n }\n\n public async getStickerSet(set: {\n id: string,\n access_hash: string\n }, params: Partial<{\n overwrite: boolean\n }> = {}): Promise<MessagesStickerSet> {\n if(this.getStickerSetPromises[set.id]) {\n return this.getStickerSetPromises[set.id];\n }\n\n return this.getStickerSetPromises[set.id] = new Promise(async(resolve, reject) => {\n if(!params.overwrite) {\n const cachedSet = await this.storage.get(set.id);\n if(cachedSet && cachedSet.documents?.length) {\n this.saveStickers(cachedSet.documents);\n resolve(cachedSet);\n delete this.getStickerSetPromises[set.id];\n return;\n }\n }\n\n try {\n const stickerSet = await apiManager.invokeApi('messages.getStickerSet', {\n stickerset: this.getStickerSetInput(set)\n });\n \n this.saveStickerSet(stickerSet, set.id);\n \n resolve(stickerSet);\n } catch(err) {\n resolve(null);\n }\n \n delete this.getStickerSetPromises[set.id];\n });\n }\n\n public async getRecentStickers(): Promise<Modify<MessagesRecentStickers.messagesRecentStickers, {\n stickers: Document[]\n }>> {\n const res = await apiManager.invokeApiHashable('messages.getRecentStickers') as MessagesRecentStickers.messagesRecentStickers;\n\n this.saveStickers(res.stickers);\n\n return res;\n }\n\n public getAnimatedEmojiSticker(emoji: string) {\n const stickerSet = this.storage.getFromCache('emoji');\n if(!stickerSet || !stickerSet.documents) return undefined;\n\n emoji = emoji.replace(/\\ufe0f/g, '').replace(/🏻|🏼|🏽|🏾|🏿/g, '');\n const pack = stickerSet.packs.find(p => p.emoticon === emoji);\n return pack ? appDocsManager.getDoc(pack.documents[0]) : undefined;\n }\n \n public saveStickerSet(res: Omit<MessagesStickerSet.messagesStickerSet, '_'>, id: string) {\n //console.log('stickers save set', res);w\n\n const newSet: MessagesStickerSet = {\n _: 'messages.stickerSet',\n set: res.set,\n packs: res.packs,\n documents: res.documents as Document[]\n };\n \n let stickerSet = this.storage.getFromCache(id);\n if(stickerSet) {\n Object.assign(stickerSet, newSet);\n } else {\n stickerSet = this.storage.setToCache(id, newSet);\n }\n\n this.saveStickers(res.documents);\n \n //console.log('stickers wrote', this.stickerSets);\n const needSave = stickerSet.set.installed_date || id === 'emoji';\n this.storage.set({[id]: stickerSet}, !needSave);\n }\n\n public getStickerSetThumbDownloadOptions(stickerSet: StickerSet.stickerSet) {\n const thumb = stickerSet.thumbs.find(thumb => thumb._ === 'photoSize') as PhotoSize.photoSize;\n const dcId = stickerSet.thumb_dc_id;\n\n const isAnimated = stickerSet.pFlags?.animated;\n\n const input: InputFileLocation.inputStickerSetThumb = {\n _: 'inputStickerSetThumb',\n stickerset: this.getStickerSetInput(stickerSet),\n volume_id: thumb.location.volume_id,\n local_id: thumb.location.local_id\n };\n\n return {dcId, location: input, size: thumb.size, mimeType: isAnimated ? \"application/x-tgsticker\" : 'image/webp'};\n }\n\n /* public getStickerSetThumbURL(stickerSet: MTStickerSet) {\n const thumb = stickerSet.thumb;\n const dcId = stickerSet.thumb_dc_id;\n\n const isAnimated = stickerSet.pFlags?.animated;\n\n const input: inputStickerSetThumb = {\n _: 'inputStickerSetThumb',\n stickerset: this.getStickerSetInput(stickerSet),\n volume_id: thumb.location.volume_id,\n local_id: thumb.location.local_id\n };\n\n const url = getFileURL('document', this.getStickerSetThumbDownloadOptions(stickerSet));\n return url;\n\n //return promise;\n } */\n\n public getStickerSetInput(set: {id: string, access_hash: string}): InputStickerSet {\n return set.id === 'emoji' ? {\n _: 'inputStickerSetAnimatedEmoji'\n } : {\n _: 'inputStickerSetID',\n id: set.id,\n access_hash: set.access_hash\n };\n }\n\n public async getFeaturedStickers() {\n const res = await apiManager.invokeApiHashable('messages.getFeaturedStickers') as MessagesFeaturedStickers.messagesFeaturedStickers;\n \n res.sets.forEach(covered => {\n this.saveStickerSet({set: covered.set, documents: [], packs: []}, covered.set.id);\n });\n\n return res.sets;\n }\n\n public async toggleStickerSet(set: StickerSet.stickerSet) {\n if(set.installed_date) {\n const res = await apiManager.invokeApi('messages.uninstallStickerSet', {\n stickerset: this.getStickerSetInput(set)\n });\n\n if(res) {\n delete set.installed_date;\n rootScope.broadcast('stickers_deleted', set);\n this.storage.remove(set.id, true);\n return true;\n }\n } else {\n const res = await apiManager.invokeApi('messages.installStickerSet', {\n stickerset: this.getStickerSetInput(set),\n archived: false\n });\n\n if(res) {\n set.installed_date = Date.now() / 1000 | 0;\n rootScope.broadcast('stickers_installed', set);\n return true;\n }\n }\n\n return false;\n }\n\n public async searchStickerSets(query: string, excludeFeatured = true) {\n const flags = excludeFeatured ? 1 : 0;\n const res = await apiManager.invokeApiHashable('messages.searchStickerSets', {\n flags,\n exclude_featured: excludeFeatured || undefined,\n q: query\n }) as MessagesFoundStickerSets.messagesFoundStickerSets;\n\n res.sets.forEach(covered => {\n this.saveStickerSet({set: covered.set, documents: [], packs: []}, covered.set.id);\n });\n\n const foundSaved: StickerSetCovered[] = [];\n const cache = this.storage.getCache();\n for(let id in cache) {\n const {set} = cache[id];\n\n if(set.title.toLowerCase().includes(query.toLowerCase()) && !res.sets.find(c => c.set.id === set.id)) {\n foundSaved.push({_: 'stickerSetCovered', set, cover: null});\n }\n }\n\n return res.sets.concat(foundSaved);\n }\n\n public getAllStickers() {\n return apiManager.invokeApiHashable('messages.getAllStickers');\n }\n\n public preloadStickerSets() {\n return this.getAllStickers().then(allStickers => {\n return Promise.all((allStickers as MessagesAllStickers.messagesAllStickers).sets.map(set => this.getStickerSet(set)));\n });\n }\n\n public getStickersByEmoticon(emoticon: string) {\n if(this.getStickersByEmoticonsPromises[emoticon]) return this.getStickersByEmoticonsPromises[emoticon];\n\n return this.getStickersByEmoticonsPromises[emoticon] = Promise.all([\n apiManager.invokeApiHashable('messages.getStickers', {\n emoticon\n }),\n this.preloadStickerSets(),\n this.getRecentStickers()\n ]).then(([messagesStickers, installedSets, recentStickers]) => {\n const foundStickers = (messagesStickers as MessagesStickers.messagesStickers).stickers.map(sticker => appDocsManager.saveDoc(sticker));\n const cachedStickersAnimated: Document.document[] = [], cachedStickersStatic: Document.document[] = [];\n\n //console.log('getStickersByEmoticon', messagesStickers, installedSets, recentStickers);\n\n const iteratePacks = (packs: StickerPack.stickerPack[]) => {\n for(const pack of packs) {\n if(pack.emoticon.includes(emoticon)) {\n for(const docId of pack.documents) {\n const doc = appDocsManager.getDoc(docId);\n (doc.animated ? cachedStickersAnimated : cachedStickersStatic).push(doc);\n }\n }\n }\n };\n\n iteratePacks(recentStickers.packs);\n\n for(const set of installedSets) {\n iteratePacks(set.packs);\n }\n\n const stickers = [...new Set(cachedStickersAnimated.concat(cachedStickersStatic, foundStickers))]/* .filter(doc => !doc.animated) */;\n\n return stickers;\n });\n }\n}\n\nconst appStickersManager = new AppStickersManager();\nMOUNT_CLASS_TO.appStickersManager = appStickersManager;\nexport default appStickersManager;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { attachClickEvent } from \"../../../../helpers/dom\";\nimport appStickersManager from \"../../../../lib/appManagers/appStickersManager\";\nimport Button from \"../../../button\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport { wrapSticker } from \"../../../wrappers\";\nimport AppSettingsTab from \"../settings\";\n\nexport default class AppTwoStepVerificationSetTab extends SliderSuperTab {\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-set');\n this.setTitle('TwoStepVerificationPasswordSet');\n\n const section = new SettingSection({\n caption: 'TwoStepVerificationPasswordSetInfo',\n noDelimiter: true\n });\n\n const emoji = '🥳';\n const doc = appStickersManager.getAnimatedEmojiSticker(emoji);\n const stickerContainer = document.createElement('div');\n\n if(doc) {\n wrapSticker({\n doc,\n div: stickerContainer,\n loop: true,\n play: true,\n width: 160,\n height: 160\n }).then(() => {\n // this.animation = player;\n });\n } else {\n stickerContainer.classList.add('media-sticker-wrapper');\n }\n\n section.content.append(stickerContainer);\n\n const inputContent = section.generateContentElement();\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const btnReturn = Button('btn-primary btn-color-primary', {text: 'TwoStepVerificationPasswordReturnSettings'});\n\n attachClickEvent(btnReturn, (e) => {\n this.close();\n });\n\n this.slider.sliceTabsUntilTab(AppSettingsTab, this);\n\n inputWrapper.append(btnReturn);\n\n inputContent.append(inputWrapper);\n\n this.scrollable.container.append(section.container);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { AccountPassword } from \"../../../../layer\";\nimport appStickersManager from \"../../../../lib/appManagers/appStickersManager\";\nimport Button from \"../../../button\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport { wrapSticker } from \"../../../wrappers\";\nimport { attachClickEvent, canFocus, replaceContent, toggleDisability } from \"../../../../helpers/dom\";\nimport passwordManager from \"../../../../lib/mtproto/passwordManager\";\nimport AppTwoStepVerificationSetTab from \"./passwordSet\";\nimport CodeInputField from \"../../../codeInputField\";\nimport AppTwoStepVerificationEmailTab from \"./email\";\nimport { putPreloader } from \"../../../misc\";\nimport { i18n, _i18n } from \"../../../../lib/langPack\";\n\nexport default class AppTwoStepVerificationEmailConfirmationTab extends SliderSuperTab {\n public codeInputField: CodeInputField;\n public state: AccountPassword;\n public email: string;\n public length: number;\n public isFirst = false;\n\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-email-confirmation');\n this.setTitle('TwoStepAuth.RecoveryTitle');\n\n const section = new SettingSection({\n caption: true,\n noDelimiter: true\n });\n\n _i18n(section.caption, 'TwoStepAuth.ConfirmEmailCodeDesc', [this.email]);\n\n const emoji = '📬';\n const doc = appStickersManager.getAnimatedEmojiSticker(emoji);\n const stickerContainer = document.createElement('div');\n\n if(doc) {\n wrapSticker({\n doc,\n div: stickerContainer,\n loop: false,\n play: true,\n width: 160,\n height: 160,\n emoji\n }).then(() => {\n // this.animation = player;\n });\n } else {\n stickerContainer.classList.add('media-sticker-wrapper');\n }\n\n section.content.append(stickerContainer);\n\n const inputContent = section.generateContentElement();\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const inputField = this.codeInputField = new CodeInputField({\n name: 'recovery-email-code',\n label: 'TwoStepAuth.RecoveryCode',\n length: this.length,\n onFill: (code) => {\n freeze(true);\n \n passwordManager.confirmPasswordEmail('' + code)\n .then(value => {\n if(!value) {\n\n }\n\n goNext();\n })\n .catch(err => {\n switch(err.type) {\n case 'CODE_INVALID':\n inputField.input.classList.add('error');\n replaceContent(inputField.label, i18n('TwoStepAuth.RecoveryCodeInvalid'));\n break;\n\n case 'EMAIL_HASH_EXPIRED':\n inputField.input.classList.add('error');\n replaceContent(inputField.label, i18n('TwoStepAuth.RecoveryCodeExpired'));\n break;\n \n default:\n console.error('confirm error', err);\n break;\n }\n\n freeze(false);\n });\n }\n });\n\n const btnChange = Button('btn-primary btn-primary-transparent primary', {text: 'TwoStepAuth.EmailCodeChangeEmail'});\n const btnResend = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'ResendCode'});\n\n const goNext = () => {\n new AppTwoStepVerificationSetTab(this.slider).open();\n };\n\n const freeze = (disable: boolean) => {\n toggleDisability([inputField.input, btnChange, btnResend], disable);\n };\n\n attachClickEvent(btnChange, (e) => {\n freeze(true);\n passwordManager.cancelPasswordEmail().then(value => {\n this.slider.sliceTabsUntilTab(AppTwoStepVerificationEmailTab, this);\n this.close();\n }, () => {\n freeze(false);\n });\n });\n\n attachClickEvent(btnResend, (e) => {\n freeze(true);\n const d = putPreloader(btnResend);\n passwordManager.resendPasswordEmail().then(value => {\n d.remove();\n freeze(false);\n });\n });\n\n inputWrapper.append(inputField.container, btnChange, btnResend);\n\n inputContent.append(inputWrapper);\n\n this.scrollable.container.append(section.container);\n }\n\n onOpenAfterTimeout() {\n if(!canFocus(this.isFirst)) return;\n this.codeInputField.input.focus();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { AccountPassword } from \"../../../../layer\";\nimport appStickersManager from \"../../../../lib/appManagers/appStickersManager\";\nimport Button from \"../../../button\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport { wrapSticker } from \"../../../wrappers\";\nimport InputField from \"../../../inputField\";\nimport { attachClickEvent, cancelEvent, canFocus } from \"../../../../helpers/dom\";\nimport { putPreloader } from \"../../../misc\";\nimport passwordManager from \"../../../../lib/mtproto/passwordManager\";\nimport AppTwoStepVerificationSetTab from \"./passwordSet\";\nimport AppTwoStepVerificationEmailConfirmationTab from \"./emailConfirmation\";\nimport RichTextProcessor from \"../../../../lib/richtextprocessor\";\nimport PopupPeer from \"../../../popups/peer\";\n\nexport default class AppTwoStepVerificationEmailTab extends SliderSuperTab {\n public inputField: InputField;\n public state: AccountPassword;\n public plainPassword: string;\n public newPassword: string;\n public hint: string;\n public isFirst = false;\n\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-email');\n this.setTitle('RecoveryEmailTitle');\n\n const section = new SettingSection({\n caption: true,\n noDelimiter: true\n });\n\n const emoji = '💌';\n const doc = appStickersManager.getAnimatedEmojiSticker(emoji);\n const stickerContainer = document.createElement('div');\n\n if(doc) {\n wrapSticker({\n doc,\n div: stickerContainer,\n loop: false,\n play: true,\n width: 160,\n height: 160,\n emoji\n }).then(() => {\n // this.animation = player;\n });\n } else {\n stickerContainer.classList.add('media-sticker-wrapper');\n }\n\n section.content.append(stickerContainer);\n\n const inputContent = section.generateContentElement();\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const inputField = this.inputField = new InputField({\n name: 'recovery-email',\n label: 'RecoveryEmail',\n plainText: true\n });\n\n inputField.input.addEventListener('keypress', (e) => {\n if(e.key === 'Enter') {\n cancelEvent(e);\n return onContinueClick();\n }\n });\n\n inputField.input.addEventListener('input', (e) => {\n inputField.input.classList.remove('error');\n });\n\n const btnContinue = Button('btn-primary btn-color-primary', {text: 'Continue'});\n const btnSkip = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'YourEmailSkip'});\n\n const goNext = () => {\n new AppTwoStepVerificationSetTab(this.slider).open();\n };\n\n const onContinueClick = () => {\n const email = inputField.value.trim();\n const match = RichTextProcessor.matchEmail(email);\n if(!match || match[0].length !== email.length) {\n inputField.input.classList.add('error');\n return;\n }\n\n toggleButtons(true);\n const d = putPreloader(btnContinue);\n\n passwordManager.updateSettings({\n hint: this.hint,\n currentPassword: this.plainPassword,\n newPassword: this.newPassword,\n email\n }).then((value) => {\n goNext();\n }, (err) => {\n if(err.type.includes('EMAIL_UNCONFIRMED')) {\n const symbols = +err.type.match(/^EMAIL_UNCONFIRMED_(\\d+)/)[1];\n\n const tab = new AppTwoStepVerificationEmailConfirmationTab(this.slider);\n tab.state = this.state;\n tab.email = email;\n tab.length = symbols;\n tab.open();\n } else {\n console.log('password set error', err);\n }\n\n toggleButtons(false);\n d.remove();\n });\n };\n attachClickEvent(btnContinue, onContinueClick);\n\n const toggleButtons = (freeze: boolean) => {\n if(freeze) {\n btnContinue.setAttribute('disabled', 'true');\n btnSkip.setAttribute('disabled', 'true');\n } else {\n btnContinue.removeAttribute('disabled');\n btnSkip.removeAttribute('disabled');\n }\n };\n\n attachClickEvent(btnSkip, (e) => {\n const popup = new PopupPeer('popup-skip-email', {\n buttons: [{\n langKey: 'Cancel',\n isCancel: true\n }, {\n langKey: 'YourEmailSkip',\n callback: () => {\n //inputContent.classList.add('sidebar-left-section-disabled');\n toggleButtons(true);\n putPreloader(btnSkip);\n passwordManager.updateSettings({\n hint: this.hint, \n currentPassword: this.plainPassword,\n newPassword: this.newPassword,\n email: ''\n }).then(() => {\n goNext();\n }, (err) => {\n toggleButtons(false);\n });\n },\n isDanger: true,\n }], \n titleLangKey: 'YourEmailSkipWarning',\n descriptionLangKey: 'YourEmailSkipWarningText'\n });\n\n popup.show();\n });\n\n inputWrapper.append(inputField.container, btnContinue, btnSkip);\n\n inputContent.append(inputWrapper);\n\n this.scrollable.container.append(section.container);\n }\n\n onOpenAfterTimeout() {\n if(!canFocus(this.isFirst)) return;\n this.inputField.input.focus();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { AccountPassword } from \"../../../../layer\";\nimport appStickersManager from \"../../../../lib/appManagers/appStickersManager\";\nimport Button from \"../../../button\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport { wrapSticker } from \"../../../wrappers\";\nimport InputField from \"../../../inputField\";\nimport AppTwoStepVerificationEmailTab from \"./email\";\nimport { attachClickEvent, cancelEvent } from \"../../../../helpers/dom\";\nimport { toast } from \"../../../toast\";\nimport I18n from \"../../../../lib/langPack\";\n\nexport default class AppTwoStepVerificationHintTab extends SliderSuperTab {\n public inputField: InputField;\n public state: AccountPassword;\n public plainPassword: string;\n public newPassword: string;\n\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-hint');\n this.setTitle('TwoStepAuth.SetupHintTitle');\n\n const section = new SettingSection({\n noDelimiter: true\n });\n\n const emoji = '💡';\n const doc = appStickersManager.getAnimatedEmojiSticker(emoji);\n const stickerContainer = document.createElement('div');\n\n if(doc) {\n wrapSticker({\n doc,\n div: stickerContainer,\n loop: false,\n play: true,\n width: 160,\n height: 160,\n emoji\n }).then(() => {\n // this.animation = player;\n });\n } else {\n stickerContainer.classList.add('media-sticker-wrapper');\n }\n\n section.content.append(stickerContainer);\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const inputField = this.inputField = new InputField({\n name: 'hint',\n label: 'TwoStepAuth.SetupHintPlaceholder'\n });\n\n inputField.input.addEventListener('keypress', (e) => {\n if(e.key === 'Enter') {\n cancelEvent(e);\n return inputField.value ? onContinueClick() : onSkipClick();\n }\n });\n\n const goNext = (e?: Event, saveHint?: boolean) => {\n if(e) {\n cancelEvent(e);\n }\n \n const hint = saveHint ? inputField.value : undefined;\n if(hint && this.newPassword === hint) {\n toast(I18n.format('PasswordAsHintError', true));\n return;\n }\n\n const tab = new AppTwoStepVerificationEmailTab(this.slider);\n tab.state = this.state;\n tab.plainPassword = this.plainPassword;\n tab.newPassword = this.newPassword;\n tab.hint = hint;\n\n tab.open();\n };\n\n const btnContinue = Button('btn-primary btn-color-primary', {text: 'Continue'});\n const btnSkip = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'YourEmailSkip'});\n\n const onContinueClick = (e?: Event) => goNext(e, true);\n const onSkipClick = (e?: Event) => goNext(e, false);\n attachClickEvent(btnContinue, onContinueClick);\n attachClickEvent(btnSkip, onSkipClick);\n\n inputWrapper.append(inputField.container, btnContinue, btnSkip);\n\n section.content.append(inputWrapper);\n\n this.scrollable.container.append(section.container);\n }\n\n onOpenAfterTimeout() {\n this.inputField.input.focus();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { attachClickEvent, cancelEvent } from \"../../../../helpers/dom\";\nimport { AccountPassword } from \"../../../../layer\";\nimport Button from \"../../../button\";\nimport PasswordInputField from \"../../../passwordInputField\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport TrackingMonkey from \"../../../monkeys/tracking\";\nimport AppTwoStepVerificationHintTab from \"./hint\";\nimport { InputState } from \"../../../inputField\";\n\nexport default class AppTwoStepVerificationReEnterPasswordTab extends SliderSuperTab {\n public state: AccountPassword;\n public passwordInputField: PasswordInputField;\n public plainPassword: string;\n public newPassword: string;\n\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-enter-password', 'two-step-verification-re-enter-password');\n this.setTitle('PleaseReEnterPassword');\n\n const section = new SettingSection({\n noDelimiter: true\n });\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const passwordInputField = this.passwordInputField = new PasswordInputField({\n name: 're-enter-password',\n label: 'PleaseReEnterPassword'\n });\n\n const monkey = new TrackingMonkey(passwordInputField, 157);\n\n const btnContinue = Button('btn-primary btn-color-primary', {text: 'Continue'});\n\n inputWrapper.append(passwordInputField.container, btnContinue);\n section.content.append(monkey.container, inputWrapper);\n\n this.scrollable.container.append(section.container);\n\n passwordInputField.input.addEventListener('keypress', (e) => {\n if(passwordInputField.input.classList.contains('error')) {\n passwordInputField.setState(InputState.Neutral);\n }\n \n if(e.key === 'Enter') {\n return onContinueClick();\n }\n });\n\n const verifyInput = () => {\n if(this.newPassword !== passwordInputField.value) {\n passwordInputField.setError();\n return false;\n }\n\n return true;\n };\n\n const onContinueClick = (e?: Event) => {\n if(e) {\n cancelEvent(e);\n }\n\n if(!verifyInput()) return;\n\n const tab = new AppTwoStepVerificationHintTab(this.slider);\n tab.state = this.state;\n tab.plainPassword = this.plainPassword;\n tab.newPassword = this.newPassword;\n tab.open();\n };\n attachClickEvent(btnContinue, onContinueClick);\n\n return monkey.load();\n }\n \n onOpenAfterTimeout() {\n this.passwordInputField.input.focus();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport AppTwoStepVerificationTab from \".\";\nimport { SettingSection } from \"../..\";\nimport { attachClickEvent, cancelEvent, canFocus, replaceContent } from \"../../../../helpers/dom\";\nimport { AccountPassword } from \"../../../../layer\";\nimport I18n, { i18n } from \"../../../../lib/langPack\";\nimport passwordManager from \"../../../../lib/mtproto/passwordManager\";\nimport RichTextProcessor from \"../../../../lib/richtextprocessor\";\nimport Button from \"../../../button\";\nimport { putPreloader } from \"../../../misc\";\nimport PasswordMonkey from \"../../../monkeys/password\";\nimport PasswordInputField from \"../../../passwordInputField\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport AppTwoStepVerificationReEnterPasswordTab from \"./reEnterPassword\";\n\nexport default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperTab {\n public state: AccountPassword;\n public passwordInputField: PasswordInputField;\n public plainPassword: string;\n public isFirst = true;\n \n protected init() {\n const isNew = !this.state.pFlags.has_password || this.plainPassword;\n this.container.classList.add('two-step-verification', 'two-step-verification-enter-password');\n this.setTitle(isNew ? 'PleaseEnterFirstPassword' : 'PleaseEnterCurrentPassword');\n\n const section = new SettingSection({\n noDelimiter: true\n });\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const passwordInputField = this.passwordInputField = new PasswordInputField({\n name: 'enter-password',\n label: isNew ? 'PleaseEnterFirstPassword' : (this.state.hint ? undefined : 'LoginPassword'),\n labelText: !isNew && this.state.hint ? RichTextProcessor.wrapEmojiText(this.state.hint) : undefined\n });\n\n const monkey = new PasswordMonkey(passwordInputField, 157);\n\n const btnContinue = Button('btn-primary btn-color-primary');\n const textEl = new I18n.IntlElement({key: 'Continue'});\n\n btnContinue.append(textEl.element);\n\n inputWrapper.append(passwordInputField.container, btnContinue);\n section.content.append(monkey.container, inputWrapper);\n\n this.scrollable.container.append(section.container);\n\n passwordInputField.input.addEventListener('keypress', (e) => {\n if(passwordInputField.input.classList.contains('error')) {\n passwordInputField.input.classList.remove('error');\n textEl.key = 'Continue';\n textEl.update();\n }\n \n if(e.key === 'Enter') {\n return onContinueClick();\n }\n });\n\n const verifyInput = () => {\n if(!passwordInputField.value.length) {\n passwordInputField.input.classList.add('error');\n return false;\n }\n\n return true;\n };\n\n let onContinueClick: (e?: Event) => void;\n if(!isNew) {\n let getStateInterval: number;\n\n let getState = () => {\n // * just to check session relevance\n if(!getStateInterval) {\n getStateInterval = window.setInterval(getState, 10e3);\n }\n \n return passwordManager.getState().then(_state => {\n this.state = _state;\n \n if(this.state.hint) {\n passwordInputField.label.innerHTML = RichTextProcessor.wrapEmojiText(this.state.hint);\n } else {\n replaceContent(passwordInputField.label, i18n('LoginPassword'));\n }\n });\n };\n \n const submit = (e?: Event) => {\n if(!verifyInput()) {\n cancelEvent(e);\n return;\n }\n\n btnContinue.setAttribute('disabled', 'true');\n textEl.key = 'PleaseWait';\n textEl.update();\n const preloader = putPreloader(btnContinue);\n \n const plainPassword = passwordInputField.value;\n passwordManager.check(passwordInputField.value, this.state).then(auth => {\n console.log(auth);\n \n if(auth._ === 'auth.authorization') {\n clearInterval(getStateInterval);\n if(monkey) monkey.remove();\n const tab = new AppTwoStepVerificationTab(this.slider);\n tab.state = this.state;\n tab.plainPassword = plainPassword;\n tab.open();\n this.slider.removeTabFromHistory(this);\n }\n }, (err) => {\n btnContinue.removeAttribute('disabled');\n passwordInputField.input.classList.add('error');\n \n switch(err.type) {\n default:\n //btnContinue.innerText = err.type;\n textEl.key = 'TwoStepAuth.InvalidPassword';\n textEl.update();\n preloader.remove();\n passwordInputField.select();\n break;\n }\n \n getState();\n });\n };\n \n onContinueClick = submit;\n\n getState();\n } else {\n onContinueClick = (e) => {\n if(e) {\n cancelEvent(e);\n }\n\n if(!verifyInput()) return;\n\n const tab = new AppTwoStepVerificationReEnterPasswordTab(this.slider);\n tab.state = this.state;\n tab.newPassword = passwordInputField.value;\n tab.plainPassword = this.plainPassword;\n tab.open();\n };\n }\n\n attachClickEvent(btnContinue, onContinueClick);\n\n return monkey.load();\n }\n\n onOpenAfterTimeout() {\n if(!canFocus(this.isFirst)) return;\n this.passwordInputField.input.focus();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"../..\";\nimport { attachClickEvent } from \"../../../../helpers/dom\";\nimport { AccountPassword } from \"../../../../layer\";\nimport appStickersManager from \"../../../../lib/appManagers/appStickersManager\";\nimport { _i18n } from \"../../../../lib/langPack\";\nimport passwordManager from \"../../../../lib/mtproto/passwordManager\";\nimport Button from \"../../../button\";\nimport PopupPeer from \"../../../popups/peer\";\nimport { SliderSuperTab } from \"../../../slider\";\nimport { wrapSticker } from \"../../../wrappers\";\nimport AppSettingsTab from \"../settings\";\nimport AppTwoStepVerificationEmailTab from \"./email\";\nimport AppTwoStepVerificationEnterPasswordTab from \"./enterPassword\";\n\nexport default class AppTwoStepVerificationTab extends SliderSuperTab {\n public state: AccountPassword;\n public plainPassword: string;\n\n protected init() {\n this.container.classList.add('two-step-verification', 'two-step-verification-main');\n this.setTitle('TwoStepVerificationTitle');\n\n const section = new SettingSection({\n caption: true,\n noDelimiter: true\n });\n\n const emoji = '🔐';\n const doc = appStickersManager.getAnimatedEmojiSticker(emoji);\n const stickerContainer = document.createElement('div');\n\n if(doc) {\n wrapSticker({\n doc,\n div: stickerContainer,\n loop: false,\n play: true,\n width: 168,\n height: 168,\n emoji\n }).then(() => {\n // this.animation = player;\n });\n } else {\n stickerContainer.classList.add('media-sticker-wrapper');\n }\n\n section.content.append(stickerContainer);\n\n const c = section.generateContentElement();\n if(this.state.pFlags.has_password) {\n _i18n(section.caption, 'TwoStepAuth.GenericHelp');\n\n const btnChangePassword = Button('btn-primary btn-transparent', {icon: 'edit', text: 'TwoStepAuth.ChangePassword'});\n const btnDisablePassword = Button('btn-primary btn-transparent', {icon: 'passwordoff', text: 'TwoStepAuth.RemovePassword'});\n const btnSetRecoveryEmail = Button('btn-primary btn-transparent', {icon: 'email', text: this.state.pFlags.has_recovery ? 'TwoStepAuth.ChangeEmail' : 'TwoStepAuth.SetupEmail'});\n\n attachClickEvent(btnChangePassword, () => {\n const tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);\n tab.state = this.state;\n tab.plainPassword = this.plainPassword;\n tab.open();\n });\n\n attachClickEvent(btnDisablePassword, () => {\n const popup = new PopupPeer('popup-disable-password', {\n buttons: [{\n langKey: 'Disable',\n callback: () => {\n passwordManager.updateSettings({currentPassword: this.plainPassword}).then(() => {\n this.slider.sliceTabsUntilTab(AppSettingsTab, this);\n this.close();\n });\n },\n isDanger: true,\n }], \n titleLangKey: 'TurnPasswordOffQuestionTitle',\n descriptionLangKey: 'TurnPasswordOffQuestion'\n });\n\n popup.show();\n });\n\n attachClickEvent(btnSetRecoveryEmail, () => {\n const tab = new AppTwoStepVerificationEmailTab(this.slider);\n tab.state = this.state;\n tab.hint = this.state.hint;\n tab.plainPassword = this.plainPassword;\n tab.newPassword = this.plainPassword;\n tab.isFirst = true;\n tab.open();\n });\n\n c.append(btnChangePassword, btnDisablePassword, btnSetRecoveryEmail);\n } else {\n _i18n(section.caption, 'TwoStepAuth.SetPasswordHelp');\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n const btnSetPassword = Button('btn-primary btn-color-primary', {text: 'TwoStepVerificationSetPassword'});\n \n inputWrapper.append(btnSetPassword);\n c.append(inputWrapper);\n\n attachClickEvent(btnSetPassword, (e) => {\n const tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);\n tab.state = this.state;\n tab.open();\n });\n }\n\n this.scrollable.container.append(section.container);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyLastSeenTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-last-seen');\n this.setTitle('PrivacyLastSeen');\n\n const caption: LangPackKey = 'PrivacySettingsController.LastSeenDescription';\n new PrivacySection({\n tab: this,\n title: 'LastSeenTitle',\n inputKey: 'inputPrivacyKeyStatusTimestamp',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverShare', 'PrivacySettingsController.AlwaysShare'],\n appendTo: this.scrollable\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { PrivacyType } from \"../../../../lib/appManagers/appPrivacyManager\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyProfilePhotoTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-profile-photo');\n this.setTitle('PrivacyProfilePhoto');\n\n const caption: LangPackKey = 'PrivacySettingsController.ProfilePhoto.CustomHelp';\n new PrivacySection({\n tab: this,\n title: 'PrivacyProfilePhotoTitle',\n inputKey: 'inputPrivacyKeyProfilePhoto',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverShare', 'PrivacySettingsController.AlwaysShare'],\n appendTo: this.scrollable,\n skipTypes: [PrivacyType.Nobody]\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyForwardMessagesTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-forward-messages');\n this.setTitle('PrivacySettings.Forwards');\n\n const caption: LangPackKey = 'PrivacySettingsController.Forwards.CustomHelp';\n new PrivacySection({\n tab: this,\n title: 'PrivacyForwardsTitle',\n inputKey: 'inputPrivacyKeyForwards',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverAllow', 'PrivacySettingsController.AlwaysAllow'],\n appendTo: this.scrollable\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyAddToGroupsTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-add-to-groups');\n this.setTitle('PrivacySettings.Groups');\n\n const caption: LangPackKey = 'PrivacySettingsController.GroupDescription';\n new PrivacySection({\n tab: this,\n title: 'WhoCanAddMe',\n inputKey: 'inputPrivacyKeyChatInvite',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverAllow', 'PrivacySettingsController.AlwaysAllow'],\n appendTo: this.scrollable\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTabEventable } from \"../../../sliderTab\";\nimport PrivacySection from \"../../../privacySection\";\nimport { LangPackKey } from \"../../../../lib/langPack\";\n\nexport default class AppPrivacyCallsTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('privacy-tab', 'privacy-calls');\n this.setTitle('PrivacySettings.VoiceCalls');\n\n const caption: LangPackKey = 'PrivacySettingsController.PhoneCallDescription';\n new PrivacySection({\n tab: this,\n title: 'WhoCanCallMe',\n inputKey: 'inputPrivacyKeyPhoneCall',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverAllow', 'PrivacySettingsController.AlwaysAllow'],\n appendTo: this.scrollable\n });\n\n {\n const caption: LangPackKey = 'PrivacySettingsController.P2p.Desc';\n new PrivacySection({\n tab: this,\n title: 'PrivacyP2PHeader',\n inputKey: 'inputPrivacyKeyPhoneP2P',\n captions: [caption, caption, caption],\n exceptionTexts: ['PrivacySettingsController.NeverAllow', 'PrivacySettingsController.AlwaysAllow'],\n appendTo: this.scrollable\n });\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport { SettingSection } from \"..\";\nimport Button from \"../../button\";\nimport Row from \"../../row\";\nimport { Authorization } from \"../../../layer\";\nimport { formatDateAccordingToToday } from \"../../../helpers/date\";\nimport { attachContextMenuListener, openBtnMenu, positionMenu } from \"../../misc\";\nimport { attachClickEvent, toggleDisability } from \"../../../helpers/dom\";\nimport ButtonMenu from \"../../buttonMenu\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport { toast } from \"../../toast\";\nimport AppPrivacyAndSecurityTab from \"./privacyAndSecurity\";\nimport I18n from \"../../../lib/langPack\";\nimport PopupPeer from \"../../popups/peer\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\n\nexport default class AppActiveSessionsTab extends SliderSuperTab {\n public privacyTab: AppPrivacyAndSecurityTab;\n public authorizations: Authorization.authorization[];\n private menuElement: HTMLElement;\n \n protected init() {\n this.container.classList.add('active-sessions-container');\n this.setTitle('SessionsTitle');\n\n const Session = (auth: Authorization.authorization) => {\n const row = new Row({\n title: [auth.app_name, auth.app_version].join(' '),\n subtitle: [auth.ip, auth.country].join(' - '),\n clickable: true,\n titleRight: auth.pFlags.current ? undefined : formatDateAccordingToToday(new Date(Math.max(auth.date_active, auth.date_created) * 1000))\n });\n\n row.container.dataset.hash = auth.hash;\n\n const midtitle = document.createElement('div');\n midtitle.classList.add('row-midtitle');\n midtitle.innerHTML = [auth.device_model, auth.system_version].join(', ');\n\n row.subtitle.parentElement.insertBefore(midtitle, row.subtitle);\n\n return row;\n };\n\n const authorizations = this.authorizations.slice();\n\n {\n const section = new SettingSection({\n name: 'CurrentSession'\n });\n\n const auth = authorizations.findAndSplice(auth => auth.pFlags.current);\n const session = Session(auth);\n\n section.content.append(session.container);\n\n if(authorizations.length) {\n const btnTerminate = Button('btn-primary btn-transparent danger', {icon: 'stop', text: 'TerminateAllSessions'});\n attachClickEvent(btnTerminate, (e) => {\n new PopupPeer('revoke-session', {\n buttons: [{\n langKey: 'Terminate',\n isDanger: true,\n callback: () => {\n const toggle = toggleDisability([btnTerminate], true);\n apiManager.invokeApi('auth.resetAuthorizations').then(value => {\n //toggleDisability([btnTerminate], false);\n btnTerminate.remove();\n otherSection.container.remove();\n this.privacyTab.updateActiveSessions();\n }, onError).finally(() => {\n toggle();\n });\n }\n }],\n titleLangKey: 'AreYouSureSessionsTitle',\n descriptionLangKey: 'AreYouSureSessions'\n }).show();\n });\n \n section.content.append(btnTerminate);\n }\n\n this.scrollable.append(section.container);\n }\n\n if(!authorizations.length) {\n return;\n }\n\n const otherSection = new SettingSection({\n name: 'OtherSessions'\n });\n\n authorizations.forEach(auth => {\n otherSection.content.append(Session(auth).container);\n });\n\n this.scrollable.append(otherSection.container);\n\n const onError = (err: any) => {\n if(err.type === 'FRESH_RESET_AUTHORISATION_FORBIDDEN') {\n toast(I18n.format('RecentSessions.Error.FreshReset', true));\n }\n };\n\n let target: HTMLElement;\n const onTerminateClick = () => {\n const hash = target.dataset.hash;\n \n new PopupPeer('revoke-session', {\n buttons: [{\n langKey: 'Terminate',\n isDanger: true,\n callback: () => {\n apiManager.invokeApi('account.resetAuthorization', {hash})\n .then(value => {\n if(value) {\n target.remove();\n this.privacyTab.updateActiveSessions();\n }\n }, onError);\n }\n }],\n titleLangKey: 'AreYouSureSessionTitle',\n descriptionLangKey: 'TerminateSessionText'\n }).show();\n };\n\n const element = this.menuElement = ButtonMenu([{\n icon: 'stop',\n text: 'Terminate',\n onClick: onTerminateClick\n }]);\n element.id = 'active-sessions-contextmenu';\n element.classList.add('contextmenu');\n\n document.getElementById('page-chats').append(element);\n\n attachContextMenuListener(this.scrollable.container, (e) => {\n target = findUpClassName(e.target, 'row');\n if(!target || target.dataset.hash === '0') {\n return;\n }\n\n if(e instanceof MouseEvent) e.preventDefault();\n // smth\n if(e instanceof MouseEvent) e.cancelBubble = true;\n\n positionMenu(e, element);\n openBtnMenu(element);\n });\n\n attachClickEvent(this.scrollable.container, (e) => {\n target = findUpClassName(e.target, 'row');\n if(!target || target.dataset.hash === '0') {\n return;\n }\n\n onTerminateClick();\n });\n }\n\n onCloseAfterTimeout() {\n if(this.menuElement) {\n this.menuElement.remove();\n }\n\n return super.onCloseAfterTimeout();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport { SettingSection } from \"..\";\nimport { attachContextMenuListener, openBtnMenu, positionMenu } from \"../../misc\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport ButtonMenu from \"../../buttonMenu\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport Button from \"../../button\";\nimport PopupPickUser from \"../../popups/pickUser\";\nimport rootScope from \"../../../lib/rootScope\";\nimport findUpTag from \"../../../helpers/dom/findUpTag\";\n\nexport default class AppBlockedUsersTab extends SliderSuperTab {\n public peerIds: number[];\n private menuElement: HTMLElement;\n \n protected init() {\n this.container.classList.add('blocked-users-container');\n this.setTitle('BlockedUsers');\n\n {\n const section = new SettingSection({\n caption: 'BlockedUsersInfo'\n });\n\n this.scrollable.append(section.container);\n }\n\n const btnAdd = Button('btn-circle btn-corner tgico-add is-visible');\n this.content.append(btnAdd);\n\n attachClickEvent(btnAdd, (e) => {\n new PopupPickUser({\n peerTypes: ['contacts'],\n placeholder: 'BlockModal.Search.Placeholder',\n onSelect: (peerId) => {\n //console.log('block', peerId);\n appUsersManager.toggleBlock(peerId, true);\n },\n });\n }, {listenerSetter: this.listenerSetter});\n\n const list = appDialogsManager.createChatList();\n this.scrollable.container.classList.add('chatlist-container');\n this.scrollable.append(list);\n\n const add = (peerId: number, append: boolean) => {\n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: list,\n drawStatus: false,\n rippleEnabled: true,\n avatarSize: 48,\n append\n });\n\n const user = appUsersManager.getUser(peerId);\n if(user.pFlags.bot) {\n dom.lastMessageSpan.append('@' + user.username);\n } else {\n if(user.rPhone) dom.lastMessageSpan.innerHTML = user.rPhone;\n else dom.lastMessageSpan.append(user.username ? '@' + user.username : appUsersManager.getUserStatusString(peerId));\n }\n\n //dom.titleSpan.innerHTML = 'Raaid El Syed';\n //dom.lastMessageSpan.innerHTML = '+1 234 567891';\n };\n\n for(const peerId of this.peerIds) {\n add(peerId, true);\n }\n\n let target: HTMLElement;\n const onUnblock = () => {\n const peerId = +target.dataset.peerId;\n appUsersManager.toggleBlock(peerId, false);\n };\n\n const element = this.menuElement = ButtonMenu([{\n icon: 'lockoff',\n text: 'Unblock',\n onClick: onUnblock,\n options: {listenerSetter: this.listenerSetter}\n }]);\n element.id = 'blocked-users-contextmenu';\n element.classList.add('contextmenu');\n\n document.getElementById('page-chats').append(element);\n\n attachContextMenuListener(this.scrollable.container, (e) => {\n target = findUpTag(e.target, 'LI');\n if(!target) {\n return;\n }\n\n if(e instanceof MouseEvent) e.preventDefault();\n // smth\n if(e instanceof MouseEvent) e.cancelBubble = true;\n\n positionMenu(e, element);\n openBtnMenu(element);\n }, this.listenerSetter);\n\n this.listenerSetter.add(rootScope, 'peer_block', (update) => {\n const {peerId, blocked} = update;\n const li = list.querySelector(`[data-peer-id=\"${peerId}\"]`);\n if(blocked) {\n if(!li) {\n add(peerId, false);\n }\n } else {\n if(li) {\n li.remove();\n }\n }\n });\n\n const LOAD_COUNT = 50;\n let loading = false;\n this.scrollable.onScrolledBottom = () => {\n if(loading) {\n return;\n }\n\n loading = true;\n appUsersManager.getBlocked(list.childElementCount, LOAD_COUNT).then(res => {\n for(const peerId of res.peerIds) {\n add(peerId, true);\n }\n\n if(res.peerIds.length < LOAD_COUNT || list.childElementCount === res.count) {\n this.scrollable.onScrolledBottom = null;\n }\n\n this.scrollable.checkForTriggers();\n }).finally(() => {\n loading = false;\n });\n };\n }\n\n onOpenAfterTimeout() {\n this.scrollable.onScroll();\n }\n\n onCloseAfterTimeout() {\n if(this.menuElement) {\n this.menuElement.remove();\n }\n\n return super.onCloseAfterTimeout();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport { SettingSection } from \"..\";\nimport Row from \"../../row\";\nimport { AccountPassword, Authorization, InputPrivacyKey } from \"../../../layer\";\nimport appPrivacyManager, { PrivacyType } from \"../../../lib/appManagers/appPrivacyManager\";\nimport AppPrivacyPhoneNumberTab from \"./privacy/phoneNumber\";\nimport AppTwoStepVerificationTab from \"./2fa\";\nimport passwordManager from \"../../../lib/mtproto/passwordManager\";\nimport AppTwoStepVerificationEnterPasswordTab from \"./2fa/enterPassword\";\nimport AppTwoStepVerificationEmailConfirmationTab from \"./2fa/emailConfirmation\";\nimport AppPrivacyLastSeenTab from \"./privacy/lastSeen\";\nimport AppPrivacyProfilePhotoTab from \"./privacy/profilePhoto\";\nimport AppPrivacyForwardMessagesTab from \"./privacy/forwardMessages\";\nimport AppPrivacyAddToGroupsTab from \"./privacy/addToGroups\";\nimport AppPrivacyCallsTab from \"./privacy/calls\";\nimport AppActiveSessionsTab from \"./activeSessions\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport AppBlockedUsersTab from \"./blockedUsers\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport rootScope from \"../../../lib/rootScope\";\nimport { convertKeyToInputKey } from \"../../../helpers/string\";\nimport { i18n, LangPackKey, _i18n } from \"../../../lib/langPack\";\nimport { replaceContent } from \"../../../helpers/dom\";\n\nexport default class AppPrivacyAndSecurityTab extends SliderSuperTab {\n private activeSessionsRow: Row;\n private authorizations: Authorization.authorization[];\n\n protected init() {\n this.container.classList.add('privacy-container');\n this.setTitle('PrivacySettings');\n\n const SUBTITLE: LangPackKey = 'Loading';\n\n {\n const section = new SettingSection({noDelimiter: true});\n\n let blockedPeerIds: number[];\n const blockedUsersRow = new Row({\n icon: 'deleteuser',\n titleLangKey: 'BlockedUsers',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n const tab = new AppBlockedUsersTab(this.slider);\n tab.peerIds = blockedPeerIds;\n tab.open();\n }\n });\n blockedUsersRow.freezed = true;\n\n let passwordState: AccountPassword;\n const twoFactorRowOptions = {\n icon: 'lock',\n titleLangKey: 'TwoStepVerification' as LangPackKey,\n subtitleLangKey: SUBTITLE,\n clickable: (e: Event) => {\n let tab: AppTwoStepVerificationTab | AppTwoStepVerificationEnterPasswordTab | AppTwoStepVerificationEmailConfirmationTab;\n if(passwordState.pFlags.has_password) {\n tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);\n } else if(passwordState.email_unconfirmed_pattern) {\n tab = new AppTwoStepVerificationEmailConfirmationTab(this.slider);\n tab.email = passwordState.email_unconfirmed_pattern;\n tab.length = 6;\n tab.isFirst = true;\n passwordManager.resendPasswordEmail();\n } else {\n tab = new AppTwoStepVerificationTab(this.slider);\n }\n \n tab.state = passwordState;\n tab.open();\n }\n };\n \n const twoFactorRow = new Row(twoFactorRowOptions);\n twoFactorRow.freezed = true;\n\n const activeSessionsRow = this.activeSessionsRow = new Row({\n icon: 'activesessions',\n titleLangKey: 'SessionsTitle',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n const tab = new AppActiveSessionsTab(this.slider);\n tab.privacyTab = this;\n tab.authorizations = this.authorizations;\n tab.open();\n }\n });\n activeSessionsRow.freezed = true;\n\n section.content.append(blockedUsersRow.container, twoFactorRow.container, activeSessionsRow.container);\n this.scrollable.append(section.container);\n\n const setBlockedCount = (count: number) => {\n if(count) {\n replaceContent(blockedUsersRow.subtitle, i18n('PrivacySettingsController.UserCount', [count]));\n } else {\n replaceContent(blockedUsersRow.subtitle, i18n('BlockedEmpty', [count]));\n }\n };\n\n this.listenerSetter.add(rootScope, 'peer_block', () => {\n /* const {blocked, peerId} = update;\n if(!blocked) blockedPeerIds.findAndSplice(p => p === peerId);\n else blockedPeerIds.unshift(peerId);\n blockedCount += blocked ? 1 : -1;\n setBlockedCount(blockedCount); */\n updateBlocked();\n });\n\n const updateBlocked = () => {\n appUsersManager.getBlocked().then(res => {\n blockedUsersRow.freezed = false;\n setBlockedCount(res.count);\n blockedPeerIds = res.peerIds;\n });\n };\n\n updateBlocked();\n\n passwordManager.getState().then(state => {\n passwordState = state;\n replaceContent(twoFactorRow.subtitle, i18n(state.pFlags.has_password ? 'PrivacyAndSecurity.Item.On' : 'PrivacyAndSecurity.Item.Off'));\n twoFactorRow.freezed = false;\n \n //console.log('password state', state);\n });\n\n this.updateActiveSessions();\n }\n\n {\n const section = new SettingSection({name: 'PrivacyTitle'});\n\n section.content.classList.add('privacy-navigation-container');\n\n const rowsByKeys: Partial<{\n [key in InputPrivacyKey['_']]: Row\n }> = {};\n\n const numberVisibilityRow = rowsByKeys['inputPrivacyKeyPhoneNumber'] = new Row({\n titleLangKey: 'PrivacyPhoneTitle',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyPhoneNumberTab(this.slider).open();\n }\n });\n\n const lastSeenTimeRow = rowsByKeys['inputPrivacyKeyStatusTimestamp'] = new Row({\n titleLangKey: 'LastSeenTitle',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyLastSeenTab(this.slider).open();\n }\n });\n\n const photoVisibilityRow = rowsByKeys['inputPrivacyKeyProfilePhoto'] = new Row({\n titleLangKey: 'PrivacyProfilePhotoTitle',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyProfilePhotoTab(this.slider).open();\n }\n });\n\n const callRow = rowsByKeys['inputPrivacyKeyPhoneCall'] = new Row({\n titleLangKey: 'WhoCanCallMe',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyCallsTab(this.slider).open();\n }\n });\n\n const linkAccountRow = rowsByKeys['inputPrivacyKeyForwards'] = new Row({\n titleLangKey: 'PrivacyForwardsTitle',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyForwardMessagesTab(this.slider).open();\n }\n });\n\n const groupChatsAddRow = rowsByKeys['inputPrivacyKeyChatInvite'] = new Row({\n titleLangKey: 'WhoCanAddMe',\n subtitleLangKey: SUBTITLE,\n clickable: () => {\n new AppPrivacyAddToGroupsTab(this.slider).open();\n }\n });\n\n const updatePrivacyRow = (key: InputPrivacyKey['_']) => {\n const row = rowsByKeys[key];\n if(!row) {\n return;\n }\n\n appPrivacyManager.getPrivacy(key).then(rules => {\n const details = appPrivacyManager.getPrivacyRulesDetails(rules);\n const langKey = details.type === PrivacyType.Everybody ? 'PrivacySettingsController.Everbody' : (details.type === PrivacyType.Contacts ? 'PrivacySettingsController.MyContacts' : 'PrivacySettingsController.Nobody');\n const disallowLength = details.disallowPeers.users.length + details.disallowPeers.chats.length;\n const allowLength = details.allowPeers.users.length + details.allowPeers.chats.length;\n\n row.subtitle.innerHTML = '';\n const s = i18n(langKey);\n row.subtitle.append(s);\n if(disallowLength || allowLength) {\n row.subtitle.append(` (${[-disallowLength, allowLength ? '+' + allowLength : 0].filter(Boolean).join(', ')})`);\n }\n });\n };\n\n section.content.append(numberVisibilityRow.container, lastSeenTimeRow.container, photoVisibilityRow.container, callRow.container, linkAccountRow.container, groupChatsAddRow.container);\n this.scrollable.append(section.container);\n\n for(const key in rowsByKeys) {\n updatePrivacyRow(key as keyof typeof rowsByKeys);\n }\n\n rootScope.on('privacy_update', (update) => {\n updatePrivacyRow(convertKeyToInputKey(update.key._) as any);\n });\n }\n }\n\n public updateActiveSessions() {\n apiManager.invokeApi('account.getAuthorizations').then(auths => {\n this.activeSessionsRow.freezed = false;\n this.authorizations = auths.authorizations;\n _i18n(this.activeSessionsRow.subtitle, 'Privacy.Devices', [this.authorizations.length]);\n //console.log('auths', auths);\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport type ColorHsla = {\n h: number,\n s: number,\n l: number,\n a: number\n};\n\nexport type ColorRgba = [number, number, number, number];\n\n/**\n * @returns h [0, 360], s [0, 100], l [0, 100], a [0, 1]\n */\nexport function rgbaToHsla(r: number, g: number, b: number, a: number = 1): ColorHsla {\n r /= 255, g /= 255, b /= 255;\n const max = Math.max(r, g, b),\n min = Math.min(r, g, b);\n let h, s, l = (max + min) / 2;\n\n if(max === min) {\n h = s = 0; // achromatic\n } else {\n let d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n\n return {\n h: h * 360,\n s: s * 100,\n l: l * 100,\n a\n };\n}\n\n// * https://stackoverflow.com/a/9493060/6758968\n/**\n * Converts an HSL color value to RGB. Conversion formula\n * adapted from http://en.wikipedia.org/wiki/HSL_color_space.\n * Assumes h in [0, 360], s, and l are contained in the set [0, 1], a in [0, 1] and\n * returns r, g, and b in the set [0, 255].\n *\n * @param {number} h The hue\n * @param {number} s The saturation\n * @param {number} l The lightness\n * @return {Array} The RGB representation\n */\nexport function hslaToRgba(h: number, s: number, l: number, a: number): ColorRgba {\n h /= 360, s /= 100, l /= 100;\n let r: number, g: number, b: number;\n\n if(s === 0) {\n r = g = b = l; // achromatic\n } else {\n const hue2rgb = function hue2rgb(p: number, q: number, t: number) {\n if(t < 0) t += 1;\n if(t > 1) t -= 1;\n if(t < 1/6) return p + (q - p) * 6 * t;\n if(t < 1/2) return q;\n if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n return p;\n }\n\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1/3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1/3);\n }\n\n return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), Math.round(a * 255)];\n}\n\nexport function hslaStringToRgba(hsla: string) {\n const splitted = hsla.slice(5, -1).split(', ');\n const alpha = +splitted.pop();\n const arr = splitted.map((val) => {\n if(val.endsWith('%')) {\n return +val.slice(0, -1);\n }\n \n return +val;\n });\n\n return hslaToRgba(arr[0], arr[1], arr[2], alpha);\n}\n\nexport function hexaToRgba(hexa: string) {\n const arr: ColorRgba = [] as any;\n const offset = 1;\n if(hexa.length === (3 + offset)) {\n for(let i = offset; i < hexa.length; ++i) {\n arr.push(parseInt(hexa[i] + hexa[i], 16));\n }\n } else if(hexa.length === (4 + offset)) {\n for(let i = offset; i < (hexa.length - 1); ++i) {\n arr.push(parseInt(hexa[i] + hexa[i], 16));\n }\n\n arr.push(parseInt(hexa[hexa.length - 1], 16));\n } else {\n for(let i = offset; i < hexa.length; i += 2) {\n arr.push(parseInt(hexa.slice(i, i + 2), 16));\n }\n }\n\n return arr;\n}\n\nexport function hexaToHsla(hexa: string) {\n const rgba = hexaToRgba(hexa);\n return rgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]);\n}\n\nexport function rgbaToHexa(rgba: ColorRgba) {\n return '#' + rgba.map(v => ('0' + v.toString(16)).slice(-2)).join('');\n}\n\nexport function hslaStringToHexa(hsla: string) {\n return rgbaToHexa(hslaStringToRgba(hsla));\n}\n\nexport function hslaStringToHex(hsla: string) {\n return hslaStringToHexa(hsla).slice(0, -2);\n}\n","import { rgbaToHsla } from \"./color\";\n\n// * https://github.com/TelegramMessenger/Telegram-iOS/blob/3d062fff78cc6b287c74e6171f855a3500c0156d/submodules/TelegramPresentationData/Sources/PresentationData.swift#L453\nexport default function highlightningColor(rgba: [number, number, number, number?]) {\n let {h, s, l} = rgbaToHsla(rgba[0], rgba[1], rgba[2]);\n if(s > 0) {\n s = Math.min(100, s + 5 + 0.1 * (100 - s));\n }\n l = Math.max(0, l * .65);\n \n const hsla = `hsla(${h}, ${s}%, ${l}%, .4)`;\n return hsla;\n}\n","import { ColorHsla, ColorRgba, hexaToHsla, hslaToRgba, rgbaToHexa as rgbaToHexa, rgbaToHsla } from \"../helpers/color\";\nimport attachGrabListeners from \"../helpers/dom/attachGrabListeners\";\nimport { clamp } from \"../helpers/number\";\nimport InputField, { InputState } from \"./inputField\";\n\nexport type ColorPickerColor = { \n hsl: string; \n rgb: string; \n hex: string; \n hsla: string; \n rgba: string; \n hexa: string; \n rgbaArray: ColorRgba; \n};\n\nexport default class ColorPicker {\n private static BASE_CLASS = 'color-picker';\n public container: HTMLElement;\n\n private boxRect: DOMRect;\n //private boxDraggerRect: DOMRect;\n private hueRect: DOMRect;\n //private hueDraggerRect: DOMRect;\n\n\tprivate hue = 0;\n\tprivate saturation = 100;\n\tprivate lightness = 50;\n\tprivate alpha = 1;\n private elements: {\n box: SVGSVGElement,\n boxDragger: SVGSVGElement,\n sliders: HTMLElement,\n hue: SVGSVGElement,\n hueDragger: SVGSVGElement,\n saturation: SVGLinearGradientElement,\n } = {} as any;\n private hexInputField: InputField;\n private rgbInputField: InputField;\n public onChange: (color: ReturnType<ColorPicker['getCurrentColor']>) => void;\n\n constructor() {\n this.container = document.createElement('div');\n this.container.classList.add(ColorPicker.BASE_CLASS);\n\n const html = `\n <svg class=\"${ColorPicker.BASE_CLASS + '-box'}\" viewBox=\"0 0 380 198\">\n <defs>\n <linearGradient id=\"color-picker-saturation\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#fff\"></stop>\n <stop offset=\"100%\" stop-color=\"hsl(0,100%,50%)\"></stop>\n </linearGradient>\n <linearGradient id=\"color-picker-brightness\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"rgba(0,0,0,0)\"></stop>\n <stop offset=\"100%\" stop-color=\"#000\"></stop>\n </linearGradient>\n <pattern id=\"color-picker-pattern\" width=\"100%\" height=\"100%\">\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" fill=\"url(#color-picker-saturation)\"></rect>\n <rect x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" fill=\"url(#color-picker-brightness)\"></rect>\n </pattern>\n </defs>\n <rect rx=\"10\" ry=\"10\" x=\"0\" y=\"0\" width=\"380\" height=\"198\" fill=\"url(#color-picker-pattern)\"></rect>\n <svg class=\"${ColorPicker.BASE_CLASS + '-dragger'} ${ColorPicker.BASE_CLASS + '-box-dragger'}\" x=\"0\" y=\"0\">\n <circle r=\"11\" fill=\"inherit\" stroke=\"#fff\" stroke-width=\"2\"></circle>\n </svg>\n </svg>\n <div class=\"${ColorPicker.BASE_CLASS + '-sliders'}\">\n <svg class=\"${ColorPicker.BASE_CLASS + '-color-slider'}\" viewBox=\"0 0 380 24\">\n <defs>\n <linearGradient id=\"hue\" x1=\"100%\" y1=\"0%\" x2=\"0%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#f00\"></stop>\n <stop offset=\"16.666%\" stop-color=\"#f0f\"></stop>\n <stop offset=\"33.333%\" stop-color=\"#00f\"></stop>\n <stop offset=\"50%\" stop-color=\"#0ff\"></stop>\n <stop offset=\"66.666%\" stop-color=\"#0f0\"></stop>\n <stop offset=\"83.333%\" stop-color=\"#ff0\"></stop>\n <stop offset=\"100%\" stop-color=\"#f00\"></stop>\n </linearGradient>\n </defs>\n <rect rx=\"4\" ry=\"4\" x=\"0\" y=\"9\" width=\"380\" height=\"8\" fill=\"url(#hue)\"></rect>\n <svg class=\"${ColorPicker.BASE_CLASS + '-dragger'} ${ColorPicker.BASE_CLASS + '-color-slider-dragger'}\" x=\"0\" y=\"13\">\n <circle r=\"11\" fill=\"inherit\" stroke=\"#fff\" stroke-width=\"2\"></circle>\n </svg>\n </svg>\n </div>\n `;\n\n this.container.innerHTML = html;\n\n this.elements.box = this.container.firstElementChild as any;\n this.elements.boxDragger = this.elements.box.lastElementChild as any;\n this.elements.saturation = this.elements.box.firstElementChild.firstElementChild as any;\n\n this.elements.sliders = this.elements.box.nextElementSibling as any;\n\n this.elements.hue = this.elements.sliders.firstElementChild as any;\n this.elements.hueDragger = this.elements.hue.lastElementChild as any;\n\n this.hexInputField = new InputField({plainText: true, label: 'Appearance.Color.Hex'});\n this.rgbInputField = new InputField({plainText: true, label: 'Appearance.Color.RGB'});\n\n const inputs = document.createElement('div');\n inputs.className = ColorPicker.BASE_CLASS + '-inputs';\n inputs.append(this.hexInputField.container, this.rgbInputField.container);\n this.container.append(inputs);\n\n this.hexInputField.input.addEventListener('input', () => {\n let value = this.hexInputField.value.replace(/#/g, '').slice(0, 6);\n\n const match = value.match(/([a-fA-F\\d]+)/);\n const valid = match && match[0].length === value.length && [/* 3, 4, */6].includes(value.length);\n this.hexInputField.setState(valid ? InputState.Neutral : InputState.Error);\n\n value = '#' + value;\n this.hexInputField.setValueSilently(value);\n \n if(valid) {\n this.setColor(value, false, true);\n }\n });\n\n // patched https://stackoverflow.com/a/34029238/6758968\n const rgbRegExp = /^(?:rgb)?\\(?([01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\W+)([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\W+(?:([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\)?)$/;\n this.rgbInputField.input.addEventListener('input', () => {\n const match = this.rgbInputField.value.match(rgbRegExp);\n this.rgbInputField.setState(match ? InputState.Neutral : InputState.Error);\n\n if(match) {\n this.setColor(rgbaToHsla(+match[1], +match[2], +match[3]), true, false);\n }\n });\n\n this.attachBoxListeners();\n this.attachHueListeners();\n }\n\n private onGrabStart = () => {\n document.documentElement.style.cursor = this.elements.boxDragger.style.cursor = 'grabbing';\n };\n\n private onGrabEnd = () => {\n document.documentElement.style.cursor = this.elements.boxDragger.style.cursor = '';\n };\n\n private attachBoxListeners() {\n attachGrabListeners(this.elements.box as any, () => {\n this.onGrabStart();\n this.boxRect = this.elements.box.getBoundingClientRect();\n //this.boxDraggerRect = this.elements.boxDragger.getBoundingClientRect();\n }, (pos) => {\n this.saturationHandler(pos.x, pos.y);\n }, () => {\n this.onGrabEnd();\n });\n }\n\n private attachHueListeners() {\n attachGrabListeners(this.elements.hue as any, () => {\n this.onGrabStart();\n this.hueRect = this.elements.hue.getBoundingClientRect();\n //this.hueDraggerRect = this.elements.hueDragger.getBoundingClientRect();\n }, (pos) => {\n this.hueHandler(pos.x);\n }, () => {\n this.onGrabEnd();\n });\n }\n\n public setColor(color: ColorHsla | string, updateHexInput = true, updateRgbInput = true) {\n if(color === undefined) { // * set to red\n color = {\n h: 0,\n s: 100,\n l: 50,\n a: 1\n };\n } else if(typeof(color) === 'string') {\n if(color[0] === '#') {\n color = hexaToHsla(color);\n } else {\n const rgb = color.match(/[.?\\d]+/g);\n color = rgbaToHsla(+rgb[0], +rgb[1], +rgb[2], rgb[3] === undefined ? 1 : +rgb[3]);\n }\n }\n\n // Set box\n this.boxRect = this.elements.box.getBoundingClientRect();\n\n const boxX = this.boxRect.width / 100 * color.s;\n const percentY = 100 - (color.l / (100 - color.s / 2)) * 100;\n const boxY = this.boxRect.height / 100 * percentY;\n\n this.saturationHandler(this.boxRect.left + boxX, this.boxRect.top + boxY, false);\n\n // Set hue\n this.hueRect = this.elements.hue.getBoundingClientRect();\n\n const percentHue = color.h / 360;\n const hueX = this.hueRect.left + this.hueRect.width * percentHue;\n\n this.hueHandler(hueX, false);\n\n // Set values\n this.hue = color.h;\n this.saturation = color.s;\n this.lightness = color.l;\n this.alpha = color.a;\n\n this.updatePicker(updateHexInput, updateRgbInput);\n };\n\n public getCurrentColor(): ColorPickerColor {\n const rgbaArray = hslaToRgba(this.hue, this.saturation, this.lightness, this.alpha);\n const hexa = rgbaToHexa(rgbaArray);\n const hex = hexa.slice(0, -2);\n\n return {\n hsl: `hsl(${this.hue}, ${this.saturation}%, ${this.lightness}%)`,\n rgb: `rgb(${rgbaArray[0]}, ${rgbaArray[1]}, ${rgbaArray[2]})`,\n hex: hex,\n hsla: `hsla(${this.hue}, ${this.saturation}%, ${this.lightness}%, ${this.alpha})`,\n rgba: `rgba(${rgbaArray[0]}, ${rgbaArray[1]}, ${rgbaArray[2]}, ${rgbaArray[3]})`,\n hexa: hexa,\n rgbaArray: rgbaArray\n };\n }\n\n public updatePicker(updateHexInput = true, updateRgbInput = true) {\n const color = this.getCurrentColor();\n this.elements.boxDragger.setAttributeNS(null, 'fill', color.hex);\n\n if(updateHexInput) {\n this.hexInputField.setValueSilently(color.hex);\n this.hexInputField.setState(InputState.Neutral);\n }\n\n if(updateRgbInput) {\n this.rgbInputField.setValueSilently(color.rgbaArray.slice(0, -1).join(', '));\n this.rgbInputField.setState(InputState.Neutral);\n }\n\n if(this.onChange) {\n this.onChange(color);\n }\n }\n\n private hueHandler(pageX: number, update = true) {\n const eventX = clamp(pageX - this.hueRect.left, 0, this.hueRect.width);\n\n const percents = eventX / this.hueRect.width;\n this.hue = Math.round(360 * percents);\n \n const hsla = `hsla(${this.hue}, 100%, 50%, ${this.alpha})`;\n\n this.elements.hueDragger.setAttributeNS(null, 'x', (percents * 100) + '%');\n this.elements.hueDragger.setAttributeNS(null, 'fill', hsla);\n \n this.elements.saturation.lastElementChild.setAttributeNS(null, 'stop-color', hsla);\n\n if(update) {\n this.updatePicker();\n }\n }\n\n private saturationHandler(pageX: number, pageY: number, update = true) {\n const maxX = this.boxRect.width;\n const maxY = this.boxRect.height;\n\n const eventX = clamp(pageX - this.boxRect.left, 0, maxX);\n const eventY = clamp(pageY - this.boxRect.top, 0, maxY);\n\n const posX = eventX / maxX * 100;\n const posY = eventY / maxY * 100;\n \n const boxDragger = this.elements.boxDragger;\n boxDragger.setAttributeNS(null, 'x', posX + '%');\n boxDragger.setAttributeNS(null, 'y', posY + '%');\n\n const saturation = clamp(posX, 0, 100);\n\n const lightnessX = 100 - saturation / 2;\n const lightnessY = 100 - clamp(posY, 0, 100);\n\n const lightness = clamp(lightnessY / 100 * lightnessX, 0, 100);\n\n this.saturation = saturation;\n this.lightness = lightness;\n\n if(update) {\n this.updatePicker();\n }\n };\n}\n","import { SettingSection } from \"..\";\nimport { hexaToRgba } from \"../../../helpers/color\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\nimport highlightningColor from \"../../../helpers/highlightningColor\";\nimport { throttle } from \"../../../helpers/schedulers\";\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport appStateManager from \"../../../lib/appManagers/appStateManager\";\nimport rootScope from \"../../../lib/rootScope\";\nimport ColorPicker, { ColorPickerColor } from \"../../colorPicker\";\nimport { SliderSuperTab } from \"../../slider\";\n\nexport default class AppBackgroundColorTab extends SliderSuperTab {\n private colorPicker: ColorPicker;\n private grid: HTMLElement;\n private applyColor: (hex: string, updateColorPicker?: boolean) => void;\n\n init() {\n this.container.classList.add('background-container', 'background-color-container');\n this.setTitle('SetColor');\n\n const section = new SettingSection({});\n this.colorPicker = new ColorPicker();\n\n section.content.append(this.colorPicker.container);\n\n this.scrollable.append(section.container);\n\n const grid = this.grid = document.createElement('div');\n grid.classList.add('grid');\n\n const colors = [\n '#E6EBEE',\n '#B2CEE1',\n '#008DD0',\n '#C6E7CB',\n '#C4E1A6',\n '#60B16E',\n '#CCD0AF',\n '#A6A997',\n '#7A7072',\n '#FDD7AF',\n '#FDB76E',\n '#DD8851'\n ];\n\n colors.forEach(color => {\n const item = document.createElement('div');\n item.classList.add('grid-item');\n item.dataset.color = color.toLowerCase();\n\n // * need for transform scale\n const media = document.createElement('div');\n media.classList.add('grid-item-media');\n media.style.backgroundColor = color;\n\n item.append(media);\n grid.append(item);\n });\n\n attachClickEvent(grid, (e) => {\n const target = findUpClassName(e.target, 'grid-item');\n if(!target || target.classList.contains('active')) {\n return;\n }\n\n const color = target.dataset.color;\n if(!color) {\n return;\n }\n\n this.applyColor(color);\n }, {listenerSetter: this.listenerSetter});\n\n this.scrollable.append(grid);\n\n this.applyColor = throttle(this._applyColor, 16, true);\n }\n\n private setActive() {\n const active = this.grid.querySelector('.active');\n const background = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme).background;\n const target = background.type === 'color' ? this.grid.querySelector(`.grid-item[data-color=\"${background.color}\"]`) : null;\n if(active === target) {\n return;\n }\n\n if(active) {\n active.classList.remove('active');\n }\n\n if(target) {\n target.classList.add('active');\n }\n }\n\n private _applyColor = (hex: string, updateColorPicker = true) => {\n if(updateColorPicker) {\n this.colorPicker.setColor(hex);\n } else {\n const rgba = hexaToRgba(hex);\n const background = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme).background;\n const hsla = highlightningColor(rgba);\n \n background.color = hex.toLowerCase();\n background.type = 'color';\n background.highlightningColor = hsla;\n appStateManager.pushToState('settings', rootScope.settings);\n \n appImManager.applyCurrentTheme(undefined, undefined, true);\n this.setActive();\n }\n };\n\n private onColorChange = (color: ColorPickerColor) => {\n this.applyColor(color.hex, false);\n };\n\n onOpen() {\n setTimeout(() => {\n const background = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme).background;\n\n // * set active if type is color\n if(background.type === 'color') {\n this.colorPicker.onChange = this.onColorChange;\n }\n\n this.colorPicker.setColor(background.color || '#cccccc');\n \n if(background.type !== 'color') {\n this.colorPicker.onChange = this.onColorChange;\n }\n }, 0);\n }\n\n onCloseAfterTimeout() {\n this.colorPicker.onChange = undefined;\n this.colorPicker = undefined;\n\n return super.onCloseAfterTimeout();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { generateSection } from \"..\";\nimport { averageColor } from \"../../../helpers/averageColor\";\nimport blur from \"../../../helpers/blur\";\nimport { deferredPromise } from \"../../../helpers/cancellablePromise\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\nimport { requestFile } from \"../../../helpers/files\";\nimport highlightningColor from \"../../../helpers/highlightningColor\";\nimport { copy } from \"../../../helpers/object\";\nimport sequentialDom from \"../../../helpers/sequentialDom\";\nimport { AccountWallPapers, PhotoSize, WallPaper } from \"../../../layer\";\nimport appDocsManager, { MyDocument } from \"../../../lib/appManagers/appDocsManager\";\nimport appDownloadManager from \"../../../lib/appManagers/appDownloadManager\";\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport appPhotosManager from \"../../../lib/appManagers/appPhotosManager\";\nimport appStateManager, { Theme, STATE_INIT } from \"../../../lib/appManagers/appStateManager\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport rootScope from \"../../../lib/rootScope\";\nimport Button from \"../../button\";\nimport CheckboxField from \"../../checkboxField\";\nimport ProgressivePreloader from \"../../preloader\";\nimport { SliderSuperTab } from \"../../slider\";\nimport { wrapPhoto } from \"../../wrappers\";\nimport AppBackgroundColorTab from \"./backgroundColor\";\n\nlet uploadTempId = 0;\n\nexport default class AppBackgroundTab extends SliderSuperTab {\n private grid: HTMLElement;\n private tempId = 0;\n private theme: Theme;\n private clicked: Set<string> = new Set();\n private blurCheckboxField: CheckboxField;\n\n init() {\n this.container.classList.add('background-container', 'background-image-container');\n this.setTitle('ChatBackground');\n\n this.theme = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme);\n\n {\n const container = generateSection(this.scrollable);\n\n const uploadButton = Button('btn-primary btn-transparent', {icon: 'cameraadd', text: 'ChatBackground.UploadWallpaper'});\n const colorButton = Button('btn-primary btn-transparent', {icon: 'colorize', text: 'SetColor'});\n const resetButton = Button('btn-primary btn-transparent', {icon: 'favourites', text: 'Appearance.Reset'});\n\n attachClickEvent(uploadButton, this.onUploadClick, {listenerSetter: this.listenerSetter});\n\n attachClickEvent(colorButton, () => {\n new AppBackgroundColorTab(this.slider).open();\n }, {listenerSetter: this.listenerSetter});\n\n attachClickEvent(resetButton, this.onResetClick, {listenerSetter: this.listenerSetter});\n\n const blurCheckboxField = this.blurCheckboxField = new CheckboxField({\n text: 'ChatBackground.Blur', \n name: 'blur', \n checked: this.theme.background.blur,\n withRipple: true\n });\n\n this.listenerSetter.add(blurCheckboxField.input, 'change', () => {\n this.theme.background.blur = blurCheckboxField.input.checked;\n appStateManager.pushToState('settings', rootScope.settings);\n\n const active = grid.querySelector('.active') as HTMLElement;\n if(!active) return;\n\n // * wait for animation end\n setTimeout(() => {\n this.setBackgroundDocument(active.dataset.slug, appDocsManager.getDoc(active.dataset.docId));\n }, 100);\n });\n\n container.append(uploadButton, colorButton, resetButton, blurCheckboxField.label);\n }\n\n rootScope.on('background_change', this.setActive);\n\n apiManager.invokeApiHashable('account.getWallPapers').then((accountWallpapers) => {\n const wallpapers = (accountWallpapers as AccountWallPapers.accountWallPapers).wallpapers as WallPaper.wallPaper[];\n wallpapers.forEach((wallpaper) => {\n this.addWallPaper(wallpaper);\n });\n\n //console.log(accountWallpapers);\n });\n\n const grid = this.grid = document.createElement('div');\n grid.classList.add('grid');\n attachClickEvent(grid, this.onGridClick, {listenerSetter: this.listenerSetter});\n this.scrollable.append(grid);\n }\n\n private onUploadClick = () => {\n requestFile('image/x-png,image/png,image/jpeg').then(file => {\n const id = 'wallpaper-upload-' + ++uploadTempId;\n\n const thumb = {\n _: 'photoSize',\n h: 0,\n w: 0,\n location: {} as any,\n size: file.size,\n type: 'full',\n url: URL.createObjectURL(file)\n } as PhotoSize.photoSize;\n let document: MyDocument = {\n _: 'document',\n access_hash: '',\n attributes: [],\n dc_id: 0,\n file_reference: [],\n id,\n mime_type: file.type,\n size: file.size,\n downloaded: true,\n date: Date.now() / 1000,\n url: thumb.url,\n pFlags: {},\n thumbs: [thumb],\n file_name: file.name\n };\n\n document = appDocsManager.saveDoc(document);\n\n const docThumb = appPhotosManager.getDocumentCachedThumb(document.id);\n docThumb.downloaded = thumb.size;\n docThumb.url = thumb.url;\n\n let wallpaper: WallPaper.wallPaper = {\n _: 'wallPaper',\n access_hash: '',\n document: document,\n id,\n slug: id,\n pFlags: {}\n };\n\n const upload = appDownloadManager.upload(file, file.name);\n\n const deferred = deferredPromise<void>();\n deferred.addNotifyListener = upload.addNotifyListener;\n deferred.cancel = upload.cancel;\n\n upload.then(inputFile => {\n apiManager.invokeApi('account.uploadWallPaper', {\n file: inputFile,\n mime_type: file.type,\n settings: {\n _: 'wallPaperSettings'\n }\n }).then(_wallpaper => {\n const newDoc = (_wallpaper as WallPaper.wallPaper).document as MyDocument;\n newDoc.downloaded = document.downloaded;\n newDoc.url = document.url;\n\n wallpaper = _wallpaper as WallPaper.wallPaper;\n wallpaper.document = appDocsManager.saveDoc(wallpaper.document);\n\n container.dataset.docId = wallpaper.document.id;\n container.dataset.slug = wallpaper.slug;\n \n this.setBackgroundDocument(wallpaper.slug, wallpaper.document).then(deferred.resolve, deferred.reject);\n }, deferred.reject);\n }, deferred.reject);\n\n deferred.then(() => {\n this.clicked.delete(wallpaper.document.id);\n }, (err) => {\n container.remove();\n //console.error('i saw the body drop', err);\n });\n\n const preloader = new ProgressivePreloader({\n isUpload: true,\n cancelable: true,\n tryAgainOnFail: false\n });\n\n const container = this.addWallPaper(wallpaper, false);\n this.clicked.add(wallpaper.document.id);\n\n preloader.attach(container, false, deferred);\n });\n };\n\n private onResetClick = () => {\n const defaultTheme = STATE_INIT.settings.themes.find(t => t.name === this.theme.name);\n if(defaultTheme) {\n ++this.tempId;\n this.theme.background = copy(defaultTheme.background);\n appStateManager.pushToState('settings', rootScope.settings);\n appImManager.applyCurrentTheme(undefined, undefined, true);\n this.blurCheckboxField.setValueSilently(this.theme.background.blur);\n }\n };\n\n private addWallPaper(wallpaper: WallPaper.wallPaper, append = true) {\n if(wallpaper.pFlags.pattern || (wallpaper.document as MyDocument).mime_type.indexOf('application/') === 0) {\n return;\n }\n\n wallpaper.document = appDocsManager.saveDoc(wallpaper.document);\n\n const container = document.createElement('div');\n container.classList.add('grid-item');\n\n const media = document.createElement('div');\n media.classList.add('grid-item-media');\n\n const wrapped = wrapPhoto({\n photo: wallpaper.document,\n message: null,\n container: media,\n boxWidth: 0,\n boxHeight: 0,\n withoutPreloader: true\n });\n\n container.dataset.docId = wallpaper.document.id;\n container.dataset.slug = wallpaper.slug;\n\n if(this.theme.background.type === 'image' && this.theme.background.slug === wallpaper.slug) {\n container.classList.add('active');\n }\n\n (wrapped.loadPromises.thumb || wrapped.loadPromises.full).then(() => {\n sequentialDom.mutate(() => {\n container.append(media);\n });\n });\n\n this.grid[append ? 'append' : 'prepend'](container);\n\n return container;\n }\n\n private onGridClick = (e: MouseEvent | TouchEvent) => {\n const target = findUpClassName(e.target, 'grid-item') as HTMLElement;\n if(!target) return;\n\n const {docId, slug} = target.dataset;\n if(this.clicked.has(docId)) return;\n this.clicked.add(docId);\n\n const preloader = new ProgressivePreloader({\n cancelable: true,\n tryAgainOnFail: false\n });\n\n const doc = appDocsManager.getDoc(docId);\n\n const load = () => {\n const promise = this.setBackgroundDocument(slug, doc);\n if(!doc.url || this.theme.background.blur) {\n preloader.attach(target, true, promise);\n }\n };\n\n preloader.construct();\n\n attachClickEvent(target, (e) => {\n if(preloader.preloader.parentElement) {\n preloader.onClick(e);\n preloader.detach();\n } else {\n load();\n }\n }, {listenerSetter: this.listenerSetter});\n\n load();\n\n //console.log(doc);\n };\n\n private saveToCache = (slug: string, url: string) => {\n fetch(url).then(response => {\n appDownloadManager.cacheStorage.save('backgrounds/' + slug, response);\n });\n };\n\n private setBackgroundDocument = (slug: string, doc: MyDocument) => {\n let _tempId = ++this.tempId;\n const middleware = () => _tempId === this.tempId;\n\n const download = appDocsManager.downloadDoc(doc, appImManager.chat.bubbles ? appImManager.chat.bubbles.lazyLoadQueue.queueId : 0);\n\n const deferred = deferredPromise<void>();\n deferred.addNotifyListener = download.addNotifyListener;\n deferred.cancel = download.cancel;\n\n download.then(() => {\n if(!middleware()) {\n deferred.resolve();\n return;\n }\n\n const background = this.theme.background;\n const onReady = (url: string) => {\n //const perf = performance.now();\n averageColor(url).then(pixel => {\n if(!middleware()) {\n deferred.resolve();\n return;\n }\n \n const hsla = highlightningColor(Array.from(pixel) as any);\n //console.log(doc, hsla, performance.now() - perf);\n\n background.slug = slug;\n background.type = 'image';\n background.highlightningColor = hsla;\n appStateManager.pushToState('settings', rootScope.settings);\n\n this.saveToCache(slug, url);\n appImManager.applyCurrentTheme(slug, url).then(deferred.resolve);\n });\n };\n\n if(background.blur) {\n setTimeout(() => {\n blur(doc.url, 12, 4)\n .then(url => {\n if(!middleware()) {\n deferred.resolve();\n return;\n }\n\n onReady(url);\n });\n }, 200);\n } else {\n onReady(doc.url);\n }\n });\n\n return deferred;\n };\n\n private setActive = () => {\n const active = this.grid.querySelector('.active');\n const background = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme).background;\n const target = background.type === 'image' ? this.grid.querySelector(`.grid-item[data-slug=\"${background.slug}\"]`) : null;\n if(active === target) {\n return;\n }\n\n if(active) {\n active.classList.remove('active');\n }\n\n if(target) {\n target.classList.add('active');\n }\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport renderImageFromUrl from \"./dom/renderImageFromUrl\";\n\nexport const averageColor = (imageUrl: string): Promise<Uint8ClampedArray> => {\n const img = document.createElement('img');\n return new Promise<Uint8ClampedArray>((resolve) => {\n renderImageFromUrl(img, imageUrl, () => {\n const canvas = document.createElement('canvas');\n const ratio = img.naturalWidth / img.naturalHeight;\n const DIMENSIONS = 50;\n if(ratio === 1) {\n canvas.width = DIMENSIONS;\n canvas.height = canvas.width / ratio;\n } else if(ratio > 1) {\n canvas.height = DIMENSIONS;\n canvas.width = canvas.height / ratio;\n } else {\n canvas.width = canvas.height = DIMENSIONS;\n }\n \n const context = canvas.getContext('2d');\n context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, canvas.width, canvas.height);\n\n const pixel = new Array(4).fill(0);\n const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data;\n for(let i = 0; i < pixels.length; i += 4) {\n pixel[0] += pixels[i];\n pixel[1] += pixels[i + 1];\n pixel[2] += pixels[i + 2];\n pixel[3] += pixels[i + 3];\n }\n\n const pixelsLength = pixels.length / 4;\n const outPixel = new Uint8ClampedArray(4);\n outPixel[0] = pixel[0] / pixelsLength;\n outPixel[1] = pixel[1] / pixelsLength;\n outPixel[2] = pixel[2] / pixelsLength;\n outPixel[3] = pixel[3] / pixelsLength;\n resolve(outPixel);\n });\n });\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\"\nimport { generateSection } from \"..\";\nimport RangeSelector from \"../../rangeSelector\";\nimport Button from \"../../button\";\nimport CheckboxField from \"../../checkboxField\";\nimport RadioField from \"../../radioField\";\nimport appStateManager from \"../../../lib/appManagers/appStateManager\";\nimport rootScope from \"../../../lib/rootScope\";\nimport { isApple } from \"../../../helpers/userAgent\";\nimport Row from \"../../row\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport AppBackgroundTab from \"./background\";\nimport { LangPackKey, _i18n } from \"../../../lib/langPack\";\n\nexport class RangeSettingSelector {\n public container: HTMLDivElement;\n private range: RangeSelector;\n\n public onChange: (value: number) => void;\n\n constructor(name: LangPackKey, step: number, initialValue: number, minValue: number, maxValue: number) {\n const BASE_CLASS = 'range-setting-selector';\n this.container = document.createElement('div');\n this.container.classList.add(BASE_CLASS);\n\n const details = document.createElement('div');\n details.classList.add(BASE_CLASS + '-details');\n\n const nameDiv = document.createElement('div');\n nameDiv.classList.add(BASE_CLASS + '-name');\n _i18n(nameDiv, name);\n\n const valueDiv = document.createElement('div');\n valueDiv.classList.add(BASE_CLASS + '-value');\n valueDiv.innerHTML = '' + initialValue;\n\n details.append(nameDiv, valueDiv);\n\n this.range = new RangeSelector(step, initialValue, minValue, maxValue);\n this.range.setListeners();\n this.range.setHandlers({\n onScrub: value => {\n if(this.onChange) {\n this.onChange(value);\n }\n\n //console.log('font size scrub:', value);\n valueDiv.innerText = '' + value;\n }\n });\n\n this.container.append(details, this.range.container);\n }\n}\n\nexport default class AppGeneralSettingsTab extends SliderSuperTab {\n init() {\n this.container.classList.add('general-settings-container');\n this.setTitle('General');\n\n const section = generateSection.bind(null, this.scrollable);\n\n {\n const container = section('Settings');\n \n const range = new RangeSettingSelector('TextSize', 1, rootScope.settings.messagesTextSize, 12, 20);\n range.onChange = (value) => {\n appStateManager.setByKey('settings.messagesTextSize', value);\n };\n\n const chatBackgroundButton = Button('btn-primary btn-transparent', {icon: 'image', text: 'ChatBackground'});\n\n attachClickEvent(chatBackgroundButton, () => {\n new AppBackgroundTab(this.slider).open();\n });\n\n const animationsCheckboxField = new CheckboxField({\n text: 'EnableAnimations', \n name: 'animations', \n stateKey: 'settings.animationsEnabled',\n withRipple: true\n });\n \n container.append(range.container, chatBackgroundButton, animationsCheckboxField.label);\n }\n\n {\n const container = section('General.Keyboard');\n\n const form = document.createElement('form');\n\n const enterRow = new Row({\n radioField: new RadioField({\n langKey: 'General.SendShortcut.Enter', \n name: 'send-shortcut', \n value: 'enter', \n stateKey: 'settings.sendShortcut'\n }),\n subtitleLangKey: 'General.SendShortcut.NewLine.ShiftEnter'\n });\n\n const ctrlEnterRow = new Row({\n radioField: new RadioField({\n name: 'send-shortcut',\n value: 'ctrlEnter', \n stateKey: 'settings.sendShortcut'\n }),\n subtitleLangKey: 'General.SendShortcut.NewLine.Enter'\n });\n _i18n(ctrlEnterRow.radioField.main, 'General.SendShortcut.CtrlEnter', [isApple ? '⌘' : 'Ctrl']);\n \n form.append(enterRow.container, ctrlEnterRow.container);\n container.append(form);\n }\n\n {\n const container = section('AutoDownloadMedia');\n //container.classList.add('sidebar-left-section-disabled');\n\n const contactsCheckboxField = new CheckboxField({\n text: 'AutodownloadContacts', \n name: 'contacts',\n stateKey: 'settings.autoDownload.contacts',\n withRipple: true\n });\n const privateCheckboxField = new CheckboxField({\n text: 'AutodownloadPrivateChats', \n name: 'private',\n stateKey: 'settings.autoDownload.private',\n withRipple: true\n });\n const groupsCheckboxField = new CheckboxField({\n text: 'AutodownloadGroupChats', \n name: 'groups',\n stateKey: 'settings.autoDownload.groups',\n withRipple: true\n });\n const channelsCheckboxField = new CheckboxField({\n text: 'AutodownloadChannels', \n name: 'channels',\n stateKey: 'settings.autoDownload.channels',\n withRipple: true\n });\n\n container.append(contactsCheckboxField.label, privateCheckboxField.label, groupsCheckboxField.label, channelsCheckboxField.label);\n }\n\n {\n const container = section('General.AutoplayMedia');\n //container.classList.add('sidebar-left-section-disabled');\n\n const gifsCheckboxField = new CheckboxField({\n text: 'AutoplayGIF', \n name: 'gifs', \n stateKey: 'settings.autoPlay.gifs',\n withRipple: true\n });\n const videosCheckboxField = new CheckboxField({\n text: 'AutoplayVideo', \n name: 'videos', \n stateKey: 'settings.autoPlay.videos',\n withRipple: true\n });\n\n container.append(gifsCheckboxField.label, videosCheckboxField.label);\n }\n \n {\n const container = section('Telegram.InstalledStickerPacksController');\n\n const suggestCheckboxField = new CheckboxField({\n text: 'Stickers.SuggestStickers', \n name: 'suggest', \n stateKey: 'settings.stickers.suggest',\n withRipple: true\n });\n const loopCheckboxField = new CheckboxField({\n text: 'InstalledStickers.LoopAnimated', \n name: 'loop', \n stateKey: 'settings.stickers.loop',\n withRipple: true\n });\n\n container.append(suggestCheckboxField.label, loopCheckboxField.label);\n }\n }\n\n onOpen() {\n if(this.init) {\n this.init();\n this.init = null;\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appProfileManager from \"../../../lib/appManagers/appProfileManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport InputField from \"../../inputField\";\nimport { SliderSuperTab } from \"../../slider\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport EditPeer from \"../../editPeer\";\nimport { UsernameInputField } from \"../../usernameInputField\";\nimport { i18n, i18n_ } from \"../../../lib/langPack\";\n\n// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)\n\nexport default class AppEditProfileTab extends SliderSuperTab {\n private firstNameInputField: InputField;\n private lastNameInputField: InputField;\n private bioInputField: InputField;\n private usernameInputField: InputField;\n \n private profileUrlContainer: HTMLDivElement;\n private profileUrlAnchor: HTMLAnchorElement;\n\n private editPeer: EditPeer;\n\n protected async init() {\n this.container.classList.add('edit-profile-container');\n this.setTitle('EditAccount.Title');\n\n const inputFields: InputField[] = [];\n\n {\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n \n this.firstNameInputField = new InputField({\n label: 'EditProfile.FirstNameLabel',\n name: 'first-name',\n maxLength: 70\n });\n this.lastNameInputField = new InputField({\n label: 'Login.Register.LastName.Placeholder',\n name: 'last-name',\n maxLength: 64\n });\n this.bioInputField = new InputField({\n label: 'EditProfile.BioLabel',\n name: 'bio',\n maxLength: 70\n });\n \n inputWrapper.append(this.firstNameInputField.container, this.lastNameInputField.container, this.bioInputField.container);\n \n const caption = document.createElement('div');\n caption.classList.add('caption');\n i18n_({element: caption, key: 'Bio.Description'});\n\n inputFields.push(this.firstNameInputField, this.lastNameInputField, this.bioInputField);\n this.scrollable.append(inputWrapper, caption);\n }\n\n this.scrollable.append(document.createElement('hr'));\n\n this.editPeer = new EditPeer({\n peerId: appUsersManager.getSelf().id,\n inputFields,\n listenerSetter: this.listenerSetter\n });\n this.content.append(this.editPeer.nextBtn);\n this.scrollable.prepend(this.editPeer.avatarEdit.container);\n\n {\n const h2 = document.createElement('div');\n h2.classList.add('sidebar-left-h2');\n i18n_({element: h2, key: 'EditAccount.Username'});\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n this.usernameInputField = new UsernameInputField({\n peerId: 0,\n label: 'EditProfile.Username.Label',\n name: 'username',\n plainText: true,\n listenerSetter: this.listenerSetter,\n onChange: () => {\n this.editPeer.handleChange();\n this.setProfileUrl();\n },\n availableText: 'EditProfile.Username.Available',\n takenText: 'EditProfile.Username.Taken',\n invalidText: 'EditProfile.Username.Invalid'\n });\n\n inputWrapper.append(this.usernameInputField.container);\n\n const caption = document.createElement('div');\n caption.classList.add('caption');\n caption.append(i18n('EditProfile.Username.Help'));\n caption.append(document.createElement('br'), document.createElement('br'));\n\n const profileUrlContainer = this.profileUrlContainer = document.createElement('div');\n profileUrlContainer.classList.add('profile-url-container');\n \n const profileUrlAnchor = this.profileUrlAnchor = document.createElement('a');\n profileUrlAnchor.classList.add('profile-url');\n profileUrlAnchor.href = '#';\n profileUrlAnchor.target = '_blank';\n\n profileUrlContainer.append(i18n('UsernameHelpLink', [profileUrlAnchor]));\n\n caption.append(profileUrlContainer);\n\n inputFields.push(this.usernameInputField);\n this.scrollable.append(h2, inputWrapper, caption);\n }\n\n attachClickEvent(this.editPeer.nextBtn, () => {\n this.editPeer.nextBtn.disabled = true;\n\n let promises: Promise<any>[] = [];\n \n promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => {\n this.close();\n }, (err) => {\n console.error('updateProfile error:', err);\n }));\n\n if(this.editPeer.uploadAvatar) {\n promises.push(this.editPeer.uploadAvatar().then(inputFile => {\n return appProfileManager.uploadProfilePhoto(inputFile);\n }));\n }\n\n if(this.usernameInputField.isValid() && this.usernameInputField.input.classList.contains('valid')) {\n promises.push(appUsersManager.updateUsername(this.usernameInputField.value));\n }\n\n Promise.race(promises).finally(() => {\n this.editPeer.nextBtn.removeAttribute('disabled');\n });\n }, {listenerSetter: this.listenerSetter});\n\n const user = appUsersManager.getSelf();\n\n const userFull = await appProfileManager.getProfile(user.id, true);\n\n this.firstNameInputField.setOriginalValue(user.first_name, true);\n this.lastNameInputField.setOriginalValue(user.last_name, true);\n this.bioInputField.setOriginalValue(userFull.about, true);\n this.usernameInputField.setOriginalValue(user.username, true);\n\n this.setProfileUrl();\n this.editPeer.handleChange();\n }\n\n private setProfileUrl() {\n if(this.usernameInputField.input.classList.contains('error') || !this.usernameInputField.value.length) {\n this.profileUrlContainer.style.display = 'none';\n } else {\n this.profileUrlContainer.style.display = '';\n let url = 'https://t.me/' + this.usernameInputField.value;\n this.profileUrlAnchor.innerText = url;\n this.profileUrlAnchor.href = url;\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport AppSelectPeers from \"../../appSelectPeers\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport { MyDialogFilter as DialogFilter } from \"../../../lib/storages/filters\";\nimport { copy } from \"../../../helpers/object\";\nimport ButtonIcon from \"../../buttonIcon\";\nimport CheckboxField from \"../../checkboxField\";\nimport Button from \"../../button\";\nimport AppEditFolderTab from \"./editFolder\";\nimport I18n, { i18n, LangPackKey, _i18n, join } from \"../../../lib/langPack\";\nimport appMessagesManager from \"../../../lib/appManagers/appMessagesManager\";\nimport RichTextProcessor from \"../../../lib/richtextprocessor\";\nimport { SettingSection } from \"..\";\nimport { toast } from \"../../toast\";\n\nexport default class AppIncludedChatsTab extends SliderSuperTab {\n private editFolderTab: AppEditFolderTab;\n private confirmBtn: HTMLElement;\n\n private selector: AppSelectPeers;\n private type: 'included' | 'excluded';\n private filter: DialogFilter;\n private originalFilter: DialogFilter;\n\n private dialogsByFilters: Map<DialogFilter, Set<number>>;\n\n protected init() {\n this.content.remove();\n this.container.classList.add('included-chatlist-container');\n this.confirmBtn = ButtonIcon('check btn-confirm blue', {noRipple: true});\n this.confirmBtn.style.display = 'none';\n\n this.header.append(this.confirmBtn);\n\n this.confirmBtn.addEventListener('click', () => {\n const selected = this.selector.getSelected();\n\n //this.filter.pFlags = {};\n\n if(this.type === 'included') {\n for(const key in this.filter.pFlags) {\n if(key.indexOf('exclude_') === 0) {\n continue;\n }\n\n // @ts-ignore\n delete this.filter.pFlags[key];\n }\n } else {\n for(const key in this.filter.pFlags) {\n if(key.indexOf('exclude_') !== 0) {\n continue;\n }\n\n // @ts-ignore\n delete this.filter.pFlags[key];\n }\n }\n\n const peers: number[] = [];\n for(const key of selected) {\n if(typeof(key) === 'number') {\n peers.push(key);\n } else {\n // @ts-ignore\n this.filter.pFlags[key] = true;\n }\n }\n\n if(this.type === 'included') {\n this.filter.pinned_peers = this.filter.pinned_peers.filter(peerId => {\n return peers.includes(peerId); // * because I have pinned peer in include_peers too\n /* const index = peers.indexOf(peerId);\n if(index !== -1) {\n peers.splice(index, 1);\n return true;\n } else {\n return false;\n } */\n });\n } else {\n this.filter.pinned_peers = this.filter.pinned_peers.filter(peerId => {\n return !peers.includes(peerId);\n });\n }\n\n const other = this.type === 'included' ? 'exclude_peers' : 'include_peers';\n this.filter[other] = this.filter[other].filter(peerId => {\n return !peers.includes(peerId);\n });\n \n this.filter[this.type === 'included' ? 'include_peers' : 'exclude_peers'] = peers;\n //this.filter.pinned_peers = this.filter.pinned_peers.filter(peerId => this.filter.include_peers.includes(peerId));\n\n this.editFolderTab.setFilter(this.filter, false);\n this.close();\n });\n\n this.dialogsByFilters = new Map();\n return appMessagesManager.filtersStorage.getDialogFilters().then(filters => {\n for(const filter of filters) {\n this.dialogsByFilters.set(filter, new Set(appMessagesManager.dialogsStorage.getFolder(filter.id).map(d => d.peerId)));\n }\n });\n }\n\n checkbox(selected?: boolean) {\n const checkboxField = new CheckboxField({\n round: true\n });\n if(selected) {\n checkboxField.input.checked = selected;\n }\n\n return checkboxField.label;\n }\n\n renderResults = async(peerIds: number[]) => {\n //const other = this.type === 'included' ? this.filter.exclude_peers : this.filter.include_peers;\n\n await appUsersManager.getContacts();\n peerIds.forEach(peerId => {\n //if(other.includes(peerId)) return;\n\n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: this.selector.scrollable,\n drawStatus: false,\n rippleEnabled: true,\n avatarSize: 46\n });\n\n const selected = this.selector.selected.has(peerId);\n dom.containerEl.append(this.checkbox(selected));\n //if(selected) dom.listEl.classList.add('active');\n\n const foundInFilters: HTMLElement[] = [];\n this.dialogsByFilters.forEach((dialogs, filter) => {\n if(dialogs.has(peerId)) {\n const span = document.createElement('span');\n span.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);\n foundInFilters.push(span);\n }\n });\n\n const joined = join(foundInFilters, false);\n joined.forEach(el => {\n dom.lastMessageSpan.append(el);\n });\n });\n };\n\n onOpen() {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n this.confirmBtn.style.display = this.type === 'excluded' ? '' : 'none';\n this.setTitle(this.type === 'included' ? 'FilterAlwaysShow' : 'FilterNeverShow');\n\n const filter = this.filter;\n\n const fragment = document.createDocumentFragment();\n\n const categoriesSection = new SettingSection({\n noDelimiter: true,\n name: 'FilterChatTypes'\n });\n\n categoriesSection.container.classList.add('folder-categories');\n\n let details: {[flag: string]: {ico: string, text: LangPackKey}};\n if(this.type === 'excluded') {\n details = {\n exclude_muted: {ico: 'mute', text: 'ChatList.Filter.MutedChats'},\n exclude_archived: {ico: 'archive', text: 'ChatList.Filter.Archive'},\n exclude_read: {ico: 'readchats', text: 'ChatList.Filter.ReadChats'}\n };\n } else {\n details = {\n contacts: {ico: 'newprivate', text: 'ChatList.Filter.Contacts'},\n non_contacts: {ico: 'noncontacts', text: 'ChatList.Filter.NonContacts'},\n groups: {ico: 'group', text: 'ChatList.Filter.Groups'},\n broadcasts: {ico: 'newchannel', text: 'ChatList.Filter.Channels'},\n bots: {ico: 'bots', text: 'ChatList.Filter.Bots'}\n };\n }\n\n const f = document.createDocumentFragment();\n for(const key in details) {\n const button = Button('btn-primary btn-transparent folder-category-button', {icon: details[key].ico, text: details[key].text});\n button.dataset.peerId = key;\n button.append(this.checkbox());\n f.append(button);\n }\n categoriesSection.content.append(f);\n\n const chatsSection = new SettingSection({\n name: 'FilterChats'\n });\n\n fragment.append(categoriesSection.container, chatsSection.container);\n\n /////////////////\n\n const selectedPeers = (this.type === 'included' ? filter.include_peers : filter.exclude_peers).slice();\n\n this.selector = new AppSelectPeers({\n appendTo: this.container, \n onChange: this.onSelectChange, \n peerType: ['dialogs'], \n renderResultsFunc: this.renderResults,\n placeholder: 'Search'\n });\n this.selector.selected = new Set(selectedPeers);\n\n let addedInitial = false;\n const _add = this.selector.add.bind(this.selector);\n this.selector.add = (peerId, title, scroll) => {\n if(this.selector.selected.size >= 100 && addedInitial && !details[peerId]) {\n const el: HTMLInputElement = this.selector.list.querySelector(`[data-peer-id=\"${peerId}\"] [type=\"checkbox\"]`);\n if(el) {\n setTimeout(() => {\n el.checked = false;\n }, 0);\n }\n\n const str = I18n.format(this.type === 'excluded' ? 'ChatList.Filter.Exclude.LimitReached': 'ChatList.Filter.Include.LimitReached', true);\n toast(str);\n return;\n }\n\n const div = _add(peerId, details[peerId] ? i18n(details[peerId].text) : undefined, scroll);\n if(details[peerId]) {\n div.querySelector('avatar-element').classList.add('tgico-' + details[peerId].ico);\n }\n return div;\n };\n\n const parent = this.selector.list.parentElement;\n chatsSection.content.append(this.selector.list);\n parent.append(fragment);\n\n this.selector.addInitial(selectedPeers);\n addedInitial = true;\n\n for(const flag in filter.pFlags) {\n // @ts-ignore\n if(details.hasOwnProperty(flag) && !!filter.pFlags[flag]) {\n (categoriesSection.content.querySelector(`[data-peer-id=\"${flag}\"]`) as HTMLElement).click();\n }\n }\n }\n\n onSelectChange = (length: number) => {\n //const changed = !deepEqual(this.filter, this.originalFilter);\n if(this.type === 'included') {\n this.confirmBtn.style.display = length ? '' : 'none';\n }\n };\n\n onCloseAfterTimeout() {\n if(this.selector) {\n this.selector.container.remove();\n this.selector = null;\n }\n\n return super.onCloseAfterTimeout();\n }\n\n /**\n * Do not ignore arguments!\n */\n public open(filter?: DialogFilter, type?: 'included' | 'excluded', editFolderTab?: AppIncludedChatsTab['editFolderTab']) {\n this.originalFilter = filter;\n this.filter = copy(this.originalFilter);\n this.type = type;\n this.editFolderTab = editFolderTab;\n \n return super.open();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { deepEqual, copy } from \"../../../helpers/object\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport { MyDialogFilter as DialogFilter } from \"../../../lib/storages/filters\";\nimport lottieLoader, { RLottiePlayer } from \"../../../lib/lottieLoader\";\nimport { ripple } from \"../../ripple\";\nimport { SliderSuperTab } from \"../../slider\";\nimport { toast } from \"../../toast\";\nimport appMessagesManager from \"../../../lib/appManagers/appMessagesManager\";\nimport InputField from \"../../inputField\";\nimport RichTextProcessor from \"../../../lib/richtextprocessor\";\nimport ButtonIcon from \"../../buttonIcon\";\nimport ButtonMenuToggle from \"../../buttonMenuToggle\";\nimport { ButtonMenuItemOptions } from \"../../buttonMenu\";\nimport Button from \"../../button\";\nimport AppIncludedChatsTab from \"./includedChats\";\nimport { i18n, i18n_, LangPackKey } from \"../../../lib/langPack\";\nimport { SettingSection } from \"..\";\n\nconst MAX_FOLDER_NAME_LENGTH = 12;\n\nexport default class AppEditFolderTab extends SliderSuperTab {\n private caption: HTMLElement;\n private stickerContainer: HTMLElement;\n\n private confirmBtn: HTMLElement;\n private menuBtn: HTMLElement;\n private nameInputField: InputField;\n\n private include_peers: SettingSection;\n private exclude_peers: SettingSection;\n private flags: {[k in 'contacts' | 'non_contacts' | 'groups' | 'broadcasts' | 'bots' | 'exclude_muted' | 'exclude_archived' | 'exclude_read']: HTMLElement} = {} as any;\n\n private animation: RLottiePlayer;\n private filter: DialogFilter;\n private originalFilter: DialogFilter;\n\n private type: 'edit' | 'create';\n private loadAnimationPromise: Promise<void>;\n\n protected init() {\n this.container.classList.add('edit-folder-container');\n this.caption = document.createElement('div');\n this.caption.classList.add('caption');\n this.caption.append(i18n('FilterIncludeExcludeInfo'));\n this.stickerContainer = document.createElement('div');\n this.stickerContainer.classList.add('sticker-container');\n\n this.confirmBtn = ButtonIcon('check btn-confirm hide blue');\n const deleteFolderButton: ButtonMenuItemOptions = {\n icon: 'delete danger',\n text: 'FilterMenuDelete',\n onClick: () => {\n deleteFolderButton.element.setAttribute('disabled', 'true');\n appMessagesManager.filtersStorage.updateDialogFilter(this.filter, true).then(bool => {\n if(bool) {\n this.close();\n }\n }).finally(() => {\n deleteFolderButton.element.removeAttribute('disabled');\n });\n }\n };\n this.menuBtn = ButtonMenuToggle({}, 'bottom-left', [deleteFolderButton]);\n this.menuBtn.classList.add('hide');\n\n this.header.append(this.confirmBtn, this.menuBtn);\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n \n this.nameInputField = new InputField({\n label: 'FilterNameInputLabel',\n maxLength: MAX_FOLDER_NAME_LENGTH\n });\n\n inputWrapper.append(this.nameInputField.container);\n\n const generateList = (className: string, h2Text: LangPackKey, buttons: {icon: string, name?: string, withRipple?: true, text: LangPackKey}[], to: any) => {\n const section = new SettingSection({\n name: h2Text,\n noDelimiter: true\n });\n\n section.container.classList.add('folder-list', className);\n\n const categories = section.generateContentElement();\n categories.classList.add('folder-categories');\n\n buttons.forEach(o => {\n const button = Button('folder-category-button btn btn-primary btn-transparent', {\n icon: o.icon,\n text: o.text,\n noRipple: o.withRipple ? undefined : true\n });\n\n if(o.name) {\n to[o.name] = button;\n }\n\n categories.append(button);\n });\n\n return section;\n };\n\n this.include_peers = generateList('folder-list-included', 'FilterInclude', [{\n icon: 'add primary',\n text: 'ChatList.Filter.Include.AddChat',\n withRipple: true\n }, {\n text: 'ChatList.Filter.Contacts',\n icon: 'newprivate',\n name: 'contacts'\n }, {\n text: 'ChatList.Filter.NonContacts',\n icon: 'noncontacts',\n name: 'non_contacts'\n }, {\n text: 'ChatList.Filter.Groups',\n icon: 'group',\n name: 'groups'\n }, {\n text: 'ChatList.Filter.Channels',\n icon: 'channel',\n name: 'broadcasts'\n }, {\n text: 'ChatList.Filter.Bots',\n icon: 'bots',\n name: 'bots'\n }], this.flags);\n\n this.exclude_peers = generateList('folder-list-excluded', 'FilterExclude', [{\n icon: 'minus primary',\n text: 'ChatList.Filter.Exclude.AddChat',\n withRipple: true\n }, {\n text: 'ChatList.Filter.MutedChats',\n icon: 'mute',\n name: 'exclude_muted'\n }, {\n text: 'ChatList.Filter.Archive',\n icon: 'archive',\n name: 'exclude_archived'\n }, {\n text: 'ChatList.Filter.ReadChats',\n icon: 'readchats',\n name: 'exclude_read'\n }], this.flags);\n\n this.scrollable.append(this.stickerContainer, this.caption, inputWrapper, this.include_peers.container, this.exclude_peers.container);\n\n const includedFlagsContainer = this.include_peers.container.querySelector('.folder-categories');\n const excludedFlagsContainer = this.exclude_peers.container.querySelector('.folder-categories');\n\n includedFlagsContainer.querySelector('.btn').addEventListener('click', () => {\n new AppIncludedChatsTab(this.slider).open(this.filter, 'included', this);\n });\n\n excludedFlagsContainer.querySelector('.btn').addEventListener('click', () => {\n new AppIncludedChatsTab(this.slider).open(this.filter, 'excluded', this);\n });\n\n this.confirmBtn.addEventListener('click', () => {\n if(this.nameInputField.input.classList.contains('error')) {\n return;\n }\n\n if(!this.nameInputField.value.trim()) {\n this.nameInputField.input.classList.add('error');\n return;\n }\n\n let include = (Array.from(includedFlagsContainer.children) as HTMLElement[]).slice(1).reduce((acc, el) => acc + +!el.style.display, 0);\n include += this.filter.include_peers.length;\n \n if(!include) {\n toast('Please choose at least one chat for this folder.');\n return;\n }\n\n this.confirmBtn.setAttribute('disabled', 'true');\n\n let promise: Promise<boolean>;\n if(!this.filter.id) {\n promise = appMessagesManager.filtersStorage.createDialogFilter(this.filter);\n } else {\n promise = appMessagesManager.filtersStorage.updateDialogFilter(this.filter);\n }\n\n promise.then(bool => {\n if(bool) {\n this.close();\n }\n }).catch(err => {\n if(err.type === 'DIALOG_FILTERS_TOO_MUCH') {\n toast('Sorry, you can\\'t create more folders.');\n } else {\n console.error('updateDialogFilter error:', err);\n }\n }).finally(() => {\n this.confirmBtn.removeAttribute('disabled');\n });\n });\n \n this.nameInputField.input.addEventListener('input', () => {\n this.filter.title = this.nameInputField.value;\n this.editCheckForChange();\n });\n\n return this.loadAnimationPromise = lottieLoader.loadAnimationFromURL({\n container: this.stickerContainer,\n loop: false,\n autoplay: false,\n width: 86,\n height: 86\n }, 'assets/img/Folders_2.tgs').then(player => {\n this.animation = player;\n\n return lottieLoader.waitForFirstFrame(player);\n });\n }\n\n onOpenAfterTimeout() {\n this.loadAnimationPromise.then(() => {\n this.animation.autoplay = true;\n this.animation.play();\n });\n }\n\n private onCreateOpen() {\n this.caption.style.display = '';\n this.setTitle('FilterNew');\n this.menuBtn.classList.add('hide');\n this.confirmBtn.classList.remove('hide');\n this.nameInputField.value = '';\n\n for(const flag in this.flags) {\n // @ts-ignore\n this.flags[flag].style.display = 'none';\n }\n }\n\n private onEditOpen() {\n this.caption.style.display = 'none';\n this.setTitle(this.type === 'create' ? 'FilterNew' : 'FilterHeaderEdit');\n\n if(this.type === 'edit') {\n this.menuBtn.classList.remove('hide');\n this.confirmBtn.classList.add('hide');\n }\n \n const filter = this.filter;\n this.nameInputField.value = RichTextProcessor.wrapDraftText(filter.title);\n\n for(const flag in this.flags) {\n this.flags[flag as keyof AppEditFolderTab['flags']].style.display = !!filter.pFlags[flag as keyof AppEditFolderTab['flags']] ? '' : 'none';\n }\n\n (['include_peers', 'exclude_peers'] as ['include_peers', 'exclude_peers']).forEach(key => {\n const section = this[key];\n const ul = appDialogsManager.createChatList();\n\n const peers = filter[key].slice();\n\n const renderMore = (_length: number) => {\n for(let i = 0, length = Math.min(peers.length, _length); i < length; ++i) {\n const peerId = peers.shift();\n\n const {dom} = appDialogsManager.addDialogNew({\n dialog: peerId,\n container: ul,\n drawStatus: false,\n rippleEnabled: false,\n meAsSaved: true,\n avatarSize: 32\n });\n dom.lastMessageSpan.parentElement.remove();\n }\n\n if(peers.length) {\n showMore.lastElementChild.replaceWith(i18n('FilterShowMoreChats', [peers.length]));\n } else if(showMore) {\n showMore.remove();\n }\n };\n \n section.generateContentElement().append(ul);\n\n let showMore: HTMLElement;\n if(peers.length) {\n const content = section.generateContentElement();\n showMore = Button('folder-category-button btn btn-primary btn-transparent', {icon: 'down'});\n showMore.classList.add('load-more', 'rp-overflow');\n showMore.addEventListener('click', () => renderMore(20));\n showMore.append(i18n('FilterShowMoreChats', [peers.length]));\n\n content.append(showMore);\n }\n\n renderMore(4);\n });\n }\n\n editCheckForChange() {\n if(this.type === 'edit') {\n const changed = !deepEqual(this.originalFilter, this.filter);\n this.confirmBtn.classList.toggle('hide', !changed);\n this.menuBtn.classList.toggle('hide', changed);\n }\n };\n\n setFilter(filter: DialogFilter, firstTime: boolean) {\n // cleanup\n Array.from(this.container.querySelectorAll('ul, .load-more')).forEach(el => el.remove());\n\n if(firstTime) {\n this.originalFilter = filter;\n this.filter = copy(filter);\n } else {\n this.filter = filter;\n this.onEditOpen();\n this.editCheckForChange();\n }\n }\n\n public open(filter?: DialogFilter) {\n const ret = super.open();\n \n if(filter === undefined) {\n this.setFilter({\n _: 'dialogFilter',\n id: 0,\n title: '',\n pFlags: {},\n pinned_peers: [],\n include_peers: [],\n exclude_peers: []\n }, true);\n this.type = 'create';\n this.onCreateOpen();\n } else {\n this.setFilter(filter, true);\n this.type = 'edit';\n this.onEditOpen();\n }\n\n return ret;\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport lottieLoader, { RLottiePlayer } from \"../../../lib/lottieLoader\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport { attachClickEvent, cancelEvent, positionElementByIndex } from \"../../../helpers/dom\";\nimport { toast } from \"../../toast\";\nimport type { MyDialogFilter } from \"../../../lib/storages/filters\";\nimport type { DialogFilterSuggested, DialogFilter } from \"../../../layer\";\nimport type _rootScope from \"../../../lib/rootScope\";\nimport type { BroadcastEvents } from \"../../../lib/rootScope\";\nimport Button from \"../../button\";\nimport appMessagesManager from \"../../../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../../../lib/appManagers/appPeersManager\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport rootScope from \"../../../lib/rootScope\";\nimport AppEditFolderTab from \"./editFolder\";\nimport Row from \"../../row\";\nimport { SettingSection } from \"..\";\nimport { i18n, i18n_, LangPackKey, join } from \"../../../lib/langPack\";\n\nexport default class AppChatFoldersTab extends SliderSuperTab {\n private createFolderBtn: HTMLElement;\n private foldersSection: SettingSection;\n private suggestedSection: SettingSection;\n private stickerContainer: HTMLElement;\n private animation: RLottiePlayer;\n\n private filtersRendered: {[filterId: number]: HTMLElement} = {};\n private loadAnimationPromise: Promise<void>;\n\n private renderFolder(dialogFilter: DialogFilterSuggested | DialogFilter | MyDialogFilter, container?: HTMLElement, div?: HTMLElement) {\n let filter: DialogFilter | MyDialogFilter;\n let description = '';\n let d: HTMLElement[] = [];\n if(dialogFilter._ === 'dialogFilterSuggested') {\n filter = dialogFilter.filter;\n description = dialogFilter.description;\n } else {\n filter = dialogFilter;\n\n let enabledFilters = Object.keys(filter.pFlags).length;\n /* (['include_peers', 'exclude_peers'] as ['include_peers', 'exclude_peers']).forEach(key => {\n enabledFilters += +!!filter[key].length;\n }); */\n \n if(enabledFilters === 1) {\n const pFlags = filter.pFlags;\n let k: LangPackKey;\n if(pFlags.contacts) k = 'FilterAllContacts';\n else if(pFlags.non_contacts) k = 'FilterAllNonContacts';\n else if(pFlags.groups) k = 'FilterAllGroups';\n else if(pFlags.broadcasts) k = 'FilterAllChannels';\n else if(pFlags.bots) k = 'FilterAllBots';\n d.push(i18n(k));\n } else {\n const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);\n let chats = 0, channels = 0, groups = 0;\n for(const dialog of folder) {\n if(appPeersManager.isAnyGroup(dialog.peerId)) groups++;\n else if(appPeersManager.isBroadcast(dialog.peerId)) channels++;\n else chats++;\n }\n\n if(chats) d.push(i18n('Chats', [chats]));\n if(channels) d.push(i18n('Channels', [channels]));\n if(groups) d.push(i18n('Groups', [groups]));\n }\n }\n\n if(!div) {\n const row = new Row({\n title: RichTextProcessor.wrapEmojiText(filter.title),\n subtitle: description,\n clickable: true\n });\n\n if(d.length) {\n const arr = join(d);\n arr.forEach(el => {\n row.subtitle.append(el);\n });\n }\n \n div = row.container;\n\n if(dialogFilter._ === 'dialogFilter') {\n const filterId = filter.id;\n if(!this.filtersRendered.hasOwnProperty(filter.id)) {\n attachClickEvent(div, () => {\n new AppEditFolderTab(this.slider).open(appMessagesManager.filtersStorage.filters[filterId]);\n }, {listenerSetter: this.listenerSetter});\n }\n\n this.filtersRendered[filter.id] = div;\n }\n }\n\n if((filter as MyDialogFilter).hasOwnProperty('orderIndex')) {\n // ! header will be at 0 index\n positionElementByIndex(div, div.parentElement || container, (filter as MyDialogFilter).orderIndex);\n } else if(container) container.append(div);\n \n return div;\n }\n\n protected async init() {\n this.container.classList.add('chat-folders-container');\n this.setTitle('ChatList.Filter.List.Title');\n\n this.scrollable.container.classList.add('chat-folders');\n\n this.stickerContainer = document.createElement('div');\n this.stickerContainer.classList.add('sticker-container');\n \n const caption = document.createElement('div');\n caption.classList.add('caption');\n i18n_({element: caption, key: 'ChatList.Filter.Header'});\n \n this.createFolderBtn = Button('btn-primary btn-color-primary btn-create-folder', {\n text: 'ChatList.Filter.NewTitle',\n icon: 'add'\n });\n\n this.foldersSection = new SettingSection({\n name: 'Filters'\n });\n this.foldersSection.container.style.display = 'none';\n\n this.suggestedSection = new SettingSection({\n name: 'FilterRecommended'\n });\n this.suggestedSection.container.style.display = 'none';\n\n this.scrollable.append(this.stickerContainer, caption, this.createFolderBtn, this.foldersSection.container, this.suggestedSection.container);\n\n attachClickEvent(this.createFolderBtn, () => {\n if(Object.keys(this.filtersRendered).length >= 10) {\n toast('Sorry, you can\\'t create more folders.');\n } else {\n new AppEditFolderTab(this.slider).open();\n }\n }, {listenerSetter: this.listenerSetter});\n\n const onFiltersContainerUpdate = () => {\n this.foldersSection.container.style.display = Object.keys(this.filtersRendered).length ? '' : 'none';\n };\n\n appMessagesManager.filtersStorage.getDialogFilters().then(filters => {\n for(const filter of filters) {\n this.renderFolder(filter, this.foldersSection.content);\n }\n\n onFiltersContainerUpdate();\n });\n\n this.listenerSetter.add(rootScope, 'filter_update', (e) => {\n const filter = e;\n if(this.filtersRendered.hasOwnProperty(filter.id)) {\n this.renderFolder(filter, null, this.filtersRendered[filter.id]);\n } else {\n this.renderFolder(filter, this.foldersSection.content);\n }\n\n onFiltersContainerUpdate();\n\n this.getSuggestedFilters();\n });\n\n this.listenerSetter.add(rootScope, 'filter_delete', (e) => {\n const filter = e;\n if(this.filtersRendered.hasOwnProperty(filter.id)) {\n /* for(const suggested of this.suggestedFilters) {\n if(deepEqual(suggested.filter, filter)) {\n \n }\n } */\n this.getSuggestedFilters();\n\n this.filtersRendered[filter.id].remove();\n delete this.filtersRendered[filter.id]\n }\n\n onFiltersContainerUpdate();\n });\n\n this.listenerSetter.add(rootScope, 'filter_order', (e: BroadcastEvents['filter_order']) => {\n const order = e;\n order.forEach((filterId, idx) => {\n const div = this.filtersRendered[filterId];\n positionElementByIndex(div, div.parentElement, idx + 1); // ! + 1 due to header \n });\n });\n\n this.getSuggestedFilters();\n\n return this.loadAnimationPromise = lottieLoader.loadAnimationFromURL({\n container: this.stickerContainer,\n loop: false,\n autoplay: false,\n width: 86,\n height: 86\n }, 'assets/img/Folders_1.tgs').then(player => {\n this.animation = player;\n\n return lottieLoader.waitForFirstFrame(player);\n });\n }\n\n onOpenAfterTimeout() {\n this.loadAnimationPromise.then(() => {\n this.animation.autoplay = true;\n this.animation.play();\n });\n }\n\n private getSuggestedFilters() {\n apiManager.invokeApi('messages.getSuggestedDialogFilters').then(suggestedFilters => {\n this.suggestedSection.container.style.display = suggestedFilters.length ? '' : 'none';\n Array.from(this.suggestedSection.content.children).slice(1).forEach(el => el.remove());\n\n suggestedFilters.forEach(filter => {\n const div = this.renderFolder(filter);\n const button = Button('btn-primary btn-color-primary', {text: 'Add'});\n div.append(button);\n this.suggestedSection.content.append(div);\n\n attachClickEvent(button, (e) => {\n cancelEvent(e);\n\n if(Object.keys(this.filtersRendered).length >= 10) {\n toast('Sorry, you can\\'t create more folders.');\n return;\n }\n\n button.setAttribute('disabled', 'true');\n\n appMessagesManager.filtersStorage.createDialogFilter(filter.filter as any).then(bool => {\n if(bool) {\n div.remove();\n }\n }).finally(() => {\n button.removeAttribute('disabled');\n });\n }, {listenerSetter: this.listenerSetter});\n });\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"..\";\nimport Row from \"../../row\";\nimport CheckboxField from \"../../checkboxField\";\nimport { InputNotifyPeer, PeerNotifySettings, Update } from \"../../../layer\";\nimport appNotificationsManager from \"../../../lib/appManagers/appNotificationsManager\";\nimport { SliderSuperTabEventable } from \"../../sliderTab\";\nimport { copy } from \"../../../helpers/object\";\nimport rootScope from \"../../../lib/rootScope\";\nimport { convertKeyToInputKey } from \"../../../helpers/string\";\nimport { LangPackKey } from \"../../../lib/langPack\";\n\ntype InputNotifyKey = Exclude<InputNotifyPeer['_'], 'inputNotifyPeer'>;\n\nexport default class AppNotificationsTab extends SliderSuperTabEventable {\n protected init() {\n this.container.classList.add('notifications-container');\n this.setTitle('Telegram.NotificationSettingsViewController');\n\n const NotifySection = (options: {\n name: LangPackKey,\n typeText: LangPackKey,\n inputKey: InputNotifyKey,\n }) => {\n const section = new SettingSection({\n name: options.name\n });\n\n const enabledRow = new Row({\n checkboxField: new CheckboxField({text: options.typeText, checked: true}),\n subtitleLangKey: 'Loading',\n });\n \n const previewEnabledRow = new Row({\n checkboxField: new CheckboxField({text: 'Notifications.MessagePreview', checked: true}),\n subtitleLangKey: 'Loading',\n });\n\n section.content.append(enabledRow.container, previewEnabledRow.container);\n\n this.scrollable.append(section.container);\n\n const inputNotifyPeer = {_: options.inputKey};\n const ret = appNotificationsManager.getNotifySettings(inputNotifyPeer);\n (ret instanceof Promise ? ret : Promise.resolve(ret)).then((notifySettings) => {\n const applySettings = () => {\n const muted = appNotificationsManager.isMuted(notifySettings);\n enabledRow.checkboxField.checked = !muted;\n previewEnabledRow.checkboxField.checked = notifySettings.show_previews;\n \n return muted;\n };\n \n applySettings();\n\n this.eventListener.addEventListener('destroy', () => {\n const mute = !enabledRow.checkboxField.checked;\n const showPreviews = previewEnabledRow.checkboxField.checked;\n\n if(mute === appNotificationsManager.isMuted(notifySettings) && showPreviews === notifySettings.show_previews) {\n return;\n }\n\n const inputSettings: any = copy(notifySettings);\n inputSettings._ = 'inputPeerNotifySettings';\n inputSettings.mute_until = mute ? 2147483647 : 0;\n inputSettings.show_previews = showPreviews;\n\n appNotificationsManager.updateNotifySettings(inputNotifyPeer, inputSettings);\n }, true);\n\n this.listenerSetter.add(rootScope, 'notify_settings', (update: Update.updateNotifySettings) => {\n const inputKey = convertKeyToInputKey(update.peer._) as any;\n if(options.inputKey === inputKey) {\n notifySettings = update.notify_settings;\n applySettings();\n }\n });\n });\n };\n\n NotifySection({\n name: 'NotificationsPrivateChats',\n typeText: 'NotificationsForPrivateChats',\n inputKey: 'inputNotifyUsers'\n });\n\n NotifySection({\n name: 'NotificationsGroups',\n typeText: 'NotificationsForGroups',\n inputKey: 'inputNotifyChats'\n });\n\n NotifySection({\n name: 'NotificationsChannels',\n typeText: 'NotificationsForChannels',\n inputKey: 'inputNotifyBroadcasts'\n });\n\n {\n const section = new SettingSection({\n name: 'NotificationsOther'\n });\n\n const contactsSignUpRow = new Row({\n checkboxField: new CheckboxField({text: 'ContactJoined', checked: true}),\n subtitleLangKey: 'Loading',\n });\n \n const soundRow = new Row({\n checkboxField: new CheckboxField({text: 'Notifications.Sound', checked: true, stateKey: 'settings.notifications.sound'}),\n subtitleLangKey: 'Checkbox.Enabled',\n });\n\n section.content.append(contactsSignUpRow.container, soundRow.container);\n\n this.scrollable.append(section.container);\n\n appNotificationsManager.getContactSignUpNotification().then(enabled => {\n contactsSignUpRow.checkboxField.checked = enabled;\n\n this.eventListener.addEventListener('destroy', () => {\n const _enabled = contactsSignUpRow.checkboxField.checked;\n if(enabled !== _enabled) {\n appNotificationsManager.setContactSignUpNotification(!_enabled);\n }\n }, true);\n });\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SettingSection } from \"..\";\nimport { randomLong } from \"../../../helpers/random\";\nimport I18n from \"../../../lib/langPack\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport RadioField from \"../../radioField\";\nimport Row, { RadioFormFromRows } from \"../../row\";\nimport { SliderSuperTab } from \"../../slider\"\n\nexport default class AppLanguageTab extends SliderSuperTab {\n protected async init() {\n this.container.classList.add('language-container');\n this.setTitle('Telegram.LanguageViewController');\n\n const section = new SettingSection({});\n\n const radioRows: Map<string, Row> = new Map();\n\n const promise = apiManager.invokeApiCacheable('langpack.getLanguages', {\n lang_pack: 'macos'\n }).then((languages) => {\n const random = randomLong();\n languages.forEach((language) => {\n const row = new Row({\n radioField: new RadioField({\n text: language.name, \n name: random, \n value: language.lang_code\n }),\n subtitle: language.native_name\n });\n \n radioRows.set(language.lang_code, row);\n });\n\n const form = RadioFormFromRows([...radioRows.values()], (value) => {\n I18n.getLangPack(value);\n });\n \n I18n.getCacheLangPack().then(langPack => {\n const row = radioRows.get(langPack.lang_code);\n if(!row) {\n console.error('no row', row, langPack);\n return;\n }\n \n row.radioField.setValueSilently(true);\n });\n \n section.content.append(form);\n });\n\n this.scrollable.append(section.container);\n\n return promise;\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport AvatarElement from \"../../avatar\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport ButtonMenuToggle from \"../../buttonMenuToggle\";\nimport Button from \"../../button\";\nimport AppPrivacyAndSecurityTab from \"./privacyAndSecurity\";\nimport AppGeneralSettingsTab from \"./generalSettings\";\nimport AppEditProfileTab from \"./editProfile\";\nimport AppChatFoldersTab from \"./chatFolders\";\nimport AppNotificationsTab from \"./notifications\";\nimport PeerTitle from \"../../peerTitle\";\nimport AppLanguageTab from \"./language\";\nimport lottieLoader from \"../../../lib/lottieLoader\";\n//import AppMediaViewer from \"../../appMediaViewerNew\";\n\nexport default class AppSettingsTab extends SliderSuperTab {\n private avatarElem: AvatarElement;\n private nameDiv: HTMLElement;\n private phoneDiv: HTMLElement;\n\n private buttons: {\n edit: HTMLButtonElement,\n folders: HTMLButtonElement,\n general: HTMLButtonElement,\n notifications: HTMLButtonElement,\n privacy: HTMLButtonElement,\n language: HTMLButtonElement\n } = {} as any;\n\n protected init() {\n this.container.classList.add('settings-container');\n this.setTitle('Settings');\n \n const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{\n icon: 'logout',\n text: 'EditAccount.Logout',\n onClick: () => {\n apiManager.logOut();\n }\n }]);\n\n this.header.append(btnMenu);\n\n this.avatarElem = new AvatarElement();\n this.avatarElem.setAttribute('clickable', '');\n this.avatarElem.classList.add('profile-avatar', 'avatar-120');\n\n /* const div = document.createElement('div');\n //div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem 0 10rem auto;';\n //div.style.width = '135px';\n //div.style.height = '100px';\n div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem auto 10rem 0;';\n div.style.width = '135px';\n div.style.height = '100px';\n \n const img = document.createElement('img');\n img.src = 'assets/img/pepe.jpg';\n img.classList.add('media-photo');\n img.style.cssText = 'max-width: 100%;max-height: 100%;';\n\n div.append(img);\n\n div.addEventListener('click', () => {\n new AppMediaViewer().setSearchContext({peerId: 61004386, inputFilter: 'inputMessagesFilterPhotos'}).openMedia({\n _: 'message',\n mid: 1,\n peerId: 61004386,\n fromId: 61004386,\n message: '',\n media: {\n _: 'messageMediaPhoto',\n photo: {\n _: 'photo',\n url: img.src,\n downloaded: 111,\n sizes: [{\n _: 'photoSize',\n type: 'x',\n w: 618,\n h: 412\n }]\n }\n },\n date: Date.now() / 1000 | 0\n }, img);\n });\n\n this.scrollable.append(div); */\n \n this.nameDiv = document.createElement('div');\n this.nameDiv.classList.add('profile-name');\n\n this.phoneDiv = document.createElement('div');\n this.phoneDiv.classList.add('profile-subtitle');\n\n const buttonsDiv = document.createElement('div');\n buttonsDiv.classList.add('profile-buttons');\n\n const className = 'profile-button btn-primary btn-transparent';\n buttonsDiv.append(this.buttons.edit = Button(className, {icon: 'edit', text: 'EditAccount.Title'}));\n buttonsDiv.append(this.buttons.folders = Button(className, {icon: 'folder', text: 'AccountSettings.Filters'}));\n buttonsDiv.append(this.buttons.general = Button(className, {icon: 'settings', text: 'Telegram.GeneralSettingsViewController'}));\n buttonsDiv.append(this.buttons.notifications = Button(className, {icon: 'unmute', text: 'AccountSettings.Notifications'}));\n buttonsDiv.append(this.buttons.privacy = Button(className, {icon: 'lock', text: 'AccountSettings.PrivacyAndSecurity'}));\n buttonsDiv.append(this.buttons.language = Button(className, {icon: 'language', text: 'AccountSettings.Language'}));\n \n this.scrollable.append(this.avatarElem, this.nameDiv, this.phoneDiv, buttonsDiv);\n this.scrollable.container.classList.add('profile-content-wrapper');\n\n /* rootScope.$on('user_auth', (e) => {\n this.fillElements();\n }); */\n\n this.buttons.edit.addEventListener('click', () => {\n const tab = new AppEditProfileTab(this.slider);\n tab.open();\n });\n\n this.buttons.folders.addEventListener('click', () => {\n new AppChatFoldersTab(this.slider).open();\n });\n\n this.buttons.general.addEventListener('click', () => {\n new AppGeneralSettingsTab(this.slider).open();\n });\n\n this.buttons.notifications.addEventListener('click', () => {\n new AppNotificationsTab(this.slider).open();\n });\n\n this.buttons.privacy.addEventListener('click', () => {\n new AppPrivacyAndSecurityTab(this.slider).open();\n });\n\n this.buttons.language.addEventListener('click', () => {\n new AppLanguageTab(this.slider).open();\n });\n\n lottieLoader.loadLottieWorkers();\n\n this.fillElements();\n }\n\n public fillElements() {\n let user = appUsersManager.getSelf();\n this.avatarElem.setAttribute('peer', '' + user.id);\n\n this.nameDiv.append(new PeerTitle({peerId: user.id}).element);\n this.phoneDiv.innerHTML = user.rPhone || '';\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appSidebarLeft from \"..\";\nimport { InputFile } from \"../../../layer\";\nimport appChatsManager from \"../../../lib/appManagers/appChatsManager\";\nimport Button from \"../../button\";\nimport InputField from \"../../inputField\";\nimport { SliderSuperTab } from \"../../slider\";\nimport AvatarEdit from \"../../avatarEdit\";\nimport AppAddMembersTab from \"./addMembers\";\nimport { _i18n } from \"../../../lib/langPack\";\n\nexport default class AppNewChannelTab extends SliderSuperTab {\n private uploadAvatar: () => Promise<InputFile> = null;\n\n private channelNameInputField: InputField;\n private channelDescriptionInputField: InputField;\n private nextBtn: HTMLButtonElement;\n private avatarEdit: AvatarEdit;\n\n protected init() {\n this.container.classList.add('new-channel-container');\n this.setTitle('NewChannel');\n\n this.avatarEdit = new AvatarEdit((_upload) => {\n this.uploadAvatar = _upload;\n });\n\n const inputWrapper = document.createElement('div');\n inputWrapper.classList.add('input-wrapper');\n\n this.channelNameInputField = new InputField({\n label: 'Channel.ChannelNameHolder',\n maxLength: 128\n });\n\n this.channelDescriptionInputField = new InputField({\n label: 'Channel.DescriptionPlaceholder',\n maxLength: 255\n });\n\n inputWrapper.append(this.channelNameInputField.container, this.channelDescriptionInputField.container);\n\n const onLengthChange = () => {\n this.nextBtn.classList.toggle('is-visible', !!this.channelNameInputField.value.length && \n !this.channelNameInputField.input.classList.contains('error') && \n !this.channelDescriptionInputField.input.classList.contains('error'));\n };\n\n this.channelNameInputField.input.addEventListener('input', onLengthChange);\n this.channelDescriptionInputField.input.addEventListener('input', onLengthChange);\n\n const caption = document.createElement('div');\n caption.classList.add('caption');\n _i18n(caption, 'Channel.DescriptionHolderDescrpiton');\n\n this.nextBtn = Button('btn-corner btn-circle', {icon: 'arrow_next'});\n\n this.nextBtn.addEventListener('click', () => {\n const title = this.channelNameInputField.value;\n const about = this.channelDescriptionInputField.value;\n\n this.nextBtn.disabled = true;\n appChatsManager.createChannel(title, about).then((channelId) => {\n if(this.uploadAvatar) {\n this.uploadAvatar().then((inputFile) => {\n appChatsManager.editPhoto(channelId, inputFile);\n });\n }\n \n appSidebarLeft.removeTabFromHistory(this);\n new AppAddMembersTab(this.slider).open({\n peerId: channelId,\n type: 'channel',\n skippable: true,\n title: 'GroupAddMembers',\n placeholder: 'SendMessageTo',\n takeOut: (peerIds) => {\n return appChatsManager.inviteToChannel(Math.abs(channelId), peerIds);\n }\n });\n });\n });\n\n this.content.append(this.nextBtn);\n this.scrollable.append(this.avatarEdit.container, inputWrapper, caption);\n }\n\n public onCloseAfterTimeout() {\n this.avatarEdit.clear();\n this.uploadAvatar = null;\n this.channelNameInputField.value = '';\n this.channelDescriptionInputField.value = '';\n this.nextBtn.disabled = false;\n return super.onCloseAfterTimeout();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport appPhotosManager from \"../../../lib/appManagers/appPhotosManager\";\nimport rootScope from \"../../../lib/rootScope\";\nimport InputSearch from \"../../inputSearch\";\nimport { canFocus } from \"../../../helpers/dom\";\nimport { isMobile } from \"../../../helpers/userAgent\";\n\n// TODO: поиск по людям глобальный, если не нашло в контактах никого\n\nexport default class AppContactsTab extends SliderSuperTab {\n private list: HTMLUListElement;\n private promise: Promise<void>;\n\n private inputSearch: InputSearch;\n private alive = true;\n \n init() {\n this.container.id = 'contacts-container';\n\n this.list = appDialogsManager.createChatList(/* {avatarSize: 48, handheldsSize: 66} */);\n this.list.id = 'contacts';\n this.list.classList.add('contacts-container');\n\n appDialogsManager.setListClickListener(this.list, () => {\n (this.container.querySelector('.sidebar-close-button') as HTMLElement).click();\n }, undefined, true);\n\n this.inputSearch = new InputSearch('Search', (value) => {\n this.list.innerHTML = '';\n this.openContacts(value);\n });\n\n this.title.replaceWith(this.inputSearch.container);\n\n this.scrollable.append(this.list);\n\n // preload contacts\n // appUsersManager.getContacts();\n }\n\n onClose() {\n this.alive = false;\n /* // need to clear, and left 1 page for smooth slide\n let pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;\n (Array.from(this.list.children) as HTMLElement[]).slice(pageCount).forEach(el => el.remove()); */\n }\n\n onOpenAfterTimeout() {\n if(isMobile || !canFocus(true)) return;\n this.inputSearch.input.focus();\n }\n\n public openContacts(query?: string) {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n if(this.promise) return this.promise;\n this.scrollable.onScrolledBottom = null;\n\n this.promise = appUsersManager.getContacts(query).then(_contacts => {\n this.promise = null;\n\n if(!this.alive) {\n //console.warn('user closed contacts before it\\'s loaded');\n return;\n }\n\n const contacts = [..._contacts];\n\n if(!query) {\n contacts.findAndSplice(u => u === rootScope.myId);\n }\n /* if(query && 'saved messages'.includes(query.toLowerCase())) {\n contacts.unshift(rootScope.myID);\n } */\n\n let sorted = contacts\n .map(userId => {\n let user = appUsersManager.getUser(userId);\n let status = appUsersManager.getUserStatusForSort(user.status);\n\n return {user, status};\n })\n .sort((a, b) => b.status - a.status);\n\n let renderPage = () => {\n let pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;\n let arr = sorted.splice(0, pageCount); // надо splice!\n\n arr.forEach(({user}) => {\n let {dialog, dom} = appDialogsManager.addDialogNew({\n dialog: user.id,\n container: this.list,\n drawStatus: false,\n avatarSize: 48,\n autonomous: true\n });\n \n let status = appUsersManager.getUserStatusString(user.id);\n dom.lastMessageSpan.append(status);\n });\n\n if(!sorted.length) renderPage = undefined;\n };\n\n renderPage();\n this.scrollable.onScrolledBottom = () => {\n if(renderPage) {\n renderPage();\n } else {\n this.scrollable.onScrolledBottom = null;\n }\n };\n });\n }\n\n public open() {\n this.openContacts();\n return super.open();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDialogsManager from \"../../../lib/appManagers/appDialogsManager\";\nimport { SliderSuperTab } from \"../../slider\";\n\nexport default class AppArchivedTab extends SliderSuperTab {\n public static filterId = 1;\n public loadedAll: boolean;\n public loadDialogsPromise: Promise<any>;\n public wasFilterId: number;\n\n init() {\n this.container.id = 'chats-archived-container';\n this.setTitle('ArchivedChats');\n\n //this.scrollable = new Scrollable(this.container, 'CLA', 500);\n const chatList = appDialogsManager.chatLists[AppArchivedTab.filterId];\n this.scrollable.append(chatList);\n this.scrollable.container.addEventListener('scroll', appDialogsManager.onChatsRegularScroll);\n this.scrollable.setVirtualContainer(chatList);\n this.scrollable.onScrolledBottom = appDialogsManager.onChatsScroll;\n ///this.scroll.attachSentinels();\n\n this.listenerSetter.add(window, 'resize', () => {\n setTimeout(appDialogsManager.scroll.checkForTriggers, 0);\n });\n }\n\n onOpen() {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n this.wasFilterId = appDialogsManager.filterId;\n appDialogsManager.scroll = this.scrollable;\n appDialogsManager.filterId = AppArchivedTab.filterId;\n appDialogsManager.onTabChange();\n }\n\n // вообще, так делать нельзя, но нет времени чтобы переделать главный чатлист на слайд...\n onOpenAfterTimeout() {\n appDialogsManager.chatLists[this.wasFilterId].innerHTML = '';\n }\n\n onClose() {\n appDialogsManager.scroll = appDialogsManager._scroll;\n appDialogsManager.filterId = this.wasFilterId;\n appDialogsManager.onTabChange();\n }\n\n onCloseAfterTimeout() {\n appDialogsManager.chatLists[AppArchivedTab.filterId].innerHTML = '';\n return super.onCloseAfterTimeout();\n }\n}\n","//import { logger } from \"../polyfill\";\n/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { formatNumber } from \"../../helpers/number\";\nimport appImManager from \"../../lib/appManagers/appImManager\";\nimport appPeersManager from \"../../lib/appManagers/appPeersManager\";\nimport appStateManager, { State } from \"../../lib/appManagers/appStateManager\";\nimport appUsersManager from \"../../lib/appManagers/appUsersManager\";\nimport rootScope from \"../../lib/rootScope\";\nimport { SearchGroup } from \"../appSearch\";\nimport \"../avatar\";\nimport Scrollable, { ScrollableX } from \"../scrollable\";\nimport InputSearch from \"../inputSearch\";\nimport SidebarSlider from \"../slider\";\nimport { TransitionSlider } from \"../transition\";\nimport AppNewGroupTab from \"./tabs/newGroup\";\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport AppSearchSuper from \"../appSearchSuper.\";\nimport { DateData, fillTipDates } from \"../../helpers/date\";\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport AppSettingsTab from \"./tabs/settings\";\nimport AppNewChannelTab from \"./tabs/newChannel\";\nimport AppContactsTab from \"./tabs/contacts\";\nimport AppArchivedTab from \"./tabs/archivedTab\";\nimport AppAddMembersTab from \"./tabs/addMembers\";\nimport { i18n_, LangPackKey } from \"../../lib/langPack\";\nimport ButtonMenu, { ButtonMenuItemOptions } from \"../buttonMenu\";\nimport CheckboxField from \"../checkboxField\";\nimport { isMobileSafari } from \"../../helpers/userAgent\";\nimport appNavigationController from \"../appNavigationController\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\nimport PeerTitle from \"../peerTitle\";\nimport { replaceContent } from \"../../helpers/dom\";\nimport App from \"../../config/app\";\nimport ButtonMenuToggle from \"../buttonMenuToggle\";\n\nexport const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';\n\nexport class AppSidebarLeft extends SidebarSlider {\n private toolsBtn: HTMLButtonElement;\n private backBtn: HTMLButtonElement;\n //private searchInput = document.getElementById('global-search') as HTMLInputElement;\n private inputSearch: InputSearch;\n \n public archivedCount: HTMLSpanElement;\n\n private newBtnMenu: HTMLElement;\n\n //private log = logger('SL');\n\n private searchGroups: {[k in 'contacts' | 'globalContacts' | 'messages' | 'people' | 'recent']: SearchGroup} = {} as any;\n searchSuper: AppSearchSuper;\n\n constructor() {\n super({\n sidebarEl: document.getElementById('column-left') as HTMLDivElement,\n navigationType: 'left'\n });\n\n //this._selectTab(0); // make first tab as default\n\n this.inputSearch = new InputSearch('Search');\n const sidebarHeader = this.sidebarEl.querySelector('.item-main .sidebar-header');\n sidebarHeader.append(this.inputSearch.container);\n\n const onNewGroupClick = () => {\n new AppAddMembersTab(this).open({\n peerId: 0,\n type: 'chat',\n skippable: false,\n takeOut: (peerIds) => {\n new AppNewGroupTab(this).open(peerIds);\n },\n title: 'GroupAddMembers',\n placeholder: 'SendMessageTo'\n });\n };\n\n const onContactsClick = () => {\n new AppContactsTab(this).open();\n };\n\n //this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;\n this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;\n\n const btnArchive: ButtonMenuItemOptions & {verify?: () => boolean} = {\n icon: 'archive',\n text: 'ArchivedChats',\n onClick: () => {\n new AppArchivedTab(this).open();\n },\n verify: () => {\n const folder = appMessagesManager.dialogsStorage.getFolder(1);\n return !!folder.length;\n }\n };\n\n const themeCheckboxField = new CheckboxField({\n toggle: true,\n checked: rootScope.settings.theme === 'night'\n });\n themeCheckboxField.input.addEventListener('change', () => {\n rootScope.settings.theme = themeCheckboxField.input.checked ? 'night' : 'day';\n appStateManager.pushToState('settings', rootScope.settings);\n appImManager.applyCurrentTheme();\n });\n\n const menuButtons: (ButtonMenuItemOptions & {verify?: () => boolean})[] = [{\n icon: 'saved',\n text: 'SavedMessages',\n onClick: () => {\n setTimeout(() => { // menu doesn't close if no timeout (lol)\n appImManager.setPeer(appImManager.myId);\n }, 0);\n }\n }, btnArchive, {\n icon: 'user',\n text: 'Contacts',\n onClick: onContactsClick\n }, {\n icon: 'settings',\n text: 'Settings',\n onClick: () => {\n new AppSettingsTab(this).open();\n }\n }, {\n icon: 'darkmode',\n text: 'DarkMode',\n onClick: () => {\n \n },\n checkboxField: themeCheckboxField\n }, {\n icon: 'animations',\n text: 'Animations',\n onClick: () => {\n \n },\n checkboxField: new CheckboxField({\n toggle: true, \n checked: true,\n stateKey: 'settings.animationsEnabled',\n })\n }, {\n icon: 'help',\n text: 'TelegramFeatures',\n onClick: () => {\n appImManager.openUsername('TelegramTips');\n }\n }, {\n icon: 'bug',\n text: 'ReportBug',\n onClick: () => {\n const a = document.createElement('a');\n a.target = '_blank';\n a.href = 'https://bugs.telegram.org/?tag_ids=40&sort=time';\n document.body.append(a);\n a.click();\n setTimeout(() => {\n a.remove();\n }, 0);\n }\n }];\n\n this.toolsBtn = ButtonMenuToggle({}, 'bottom-right', menuButtons, (e) => {\n menuButtons.forEach(button => {\n if(button.verify) {\n button.element.classList.toggle('hide', !button.verify());\n }\n });\n });\n this.toolsBtn.classList.remove('tgico-more');\n this.toolsBtn.classList.add('sidebar-tools-button', 'is-visible');\n\n this.backBtn.parentElement.insertBefore(this.toolsBtn, this.backBtn);\n\n const btnMenu = this.toolsBtn.querySelector('.btn-menu') as HTMLElement;\n\n const btnMenuFooter = document.createElement('div');\n btnMenuFooter.classList.add('btn-menu-footer');\n const t = document.createElement('span');\n t.classList.add('btn-menu-footer-text');\n t.innerHTML = 'Telegram WebK alpha ' + App.version;\n btnMenuFooter.append(t); \n btnMenu.classList.add('has-footer');\n btnMenu.append(btnMenuFooter);\n\n this.newBtnMenu = ButtonMenuToggle({}, 'top-left', [{\n icon: 'newchannel',\n text: 'NewChannel',\n onClick: () => {\n new AppNewChannelTab(this).open();\n }\n }, {\n icon: 'newgroup',\n text: 'NewGroup',\n onClick: onNewGroupClick\n }, {\n icon: 'newprivate',\n text: 'NewPrivateChat',\n onClick: onContactsClick\n }]);\n this.newBtnMenu.className = 'btn-circle rp btn-corner btn-menu-toggle animated-button-icon';\n this.newBtnMenu.insertAdjacentHTML('afterbegin', `\n <span class=\"tgico tgico-newchat_filled\"></span>\n <span class=\"tgico tgico-close\"></span>\n `);\n this.newBtnMenu.id = 'new-menu';\n sidebarHeader.nextElementSibling.append(this.newBtnMenu);\n\n this.inputSearch.input.addEventListener('focus', () => this.initSearch(), {once: true});\n\n //parseMenuButtonsTo(this.newButtons, this.newBtnMenu.firstElementChild.children);\n\n this.archivedCount = document.createElement('span');\n this.archivedCount.className = 'archived-count badge badge-24 badge-gray';\n\n btnArchive.element.append(this.archivedCount);\n\n rootScope.on('dialogs_archived_unread', (e) => {\n this.archivedCount.innerText = '' + formatNumber(e.count, 1);\n this.archivedCount.classList.toggle('hide', !e.count);\n });\n\n appUsersManager.getTopPeers();\n }\n\n private initSearch() {\n const searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement;\n\n const scrollable = new Scrollable(searchContainer);\n\n const close = () => {\n //setTimeout(() => {\n this.backBtn.click();\n //}, 0);\n };\n\n this.searchGroups = {\n contacts: new SearchGroup('Chats', 'contacts', undefined, undefined, undefined, undefined, close),\n globalContacts: new SearchGroup('Global Search', 'contacts', undefined, undefined, undefined, undefined, close),\n messages: new SearchGroup('Messages', 'messages'),\n people: new SearchGroup('', 'contacts', true, 'search-group-people', true, false, close),\n recent: new SearchGroup('Recent', 'contacts', true, 'search-group-recent', true, true, close)\n };\n\n const searchSuper = this.searchSuper = new AppSearchSuper({\n mediaTabs: [{\n inputFilter: 'inputMessagesFilterEmpty',\n name: 'FilterChats',\n type: 'chats'\n }, {\n inputFilter: 'inputMessagesFilterPhotoVideo',\n name: 'SharedMediaTab2',\n type: 'media'\n }, {\n inputFilter: 'inputMessagesFilterUrl',\n name: 'SharedLinksTab2',\n type: 'links'\n }, {\n inputFilter: 'inputMessagesFilterDocument',\n name: 'SharedFilesTab2',\n type: 'files'\n }, {\n inputFilter: 'inputMessagesFilterMusic',\n name: 'SharedMusicTab2',\n type: 'music'\n }, {\n inputFilter: 'inputMessagesFilterVoice',\n name: 'SharedVoiceTab2',\n type: 'voice'\n }], \n scrollable, \n searchGroups: this.searchGroups, \n asChatList: true,\n hideEmptyTabs: false,\n showSender: true\n });\n\n searchContainer.prepend(searchSuper.nav.parentElement.parentElement);\n scrollable.container.append(searchSuper.container);\n\n const resetSearch = () => {\n searchSuper.setQuery({\n peerId: 0, \n folderId: 0\n });\n searchSuper.selectTab(0);\n searchSuper.load(true); \n };\n\n resetSearch();\n\n let pickedElements: HTMLElement[] = [];\n let selectedPeerId = 0;\n let selectedMinDate = 0;\n let selectedMaxDate = 0;\n const updatePicked = () => {\n //(this.inputSearch.input as HTMLInputElement).placeholder = pickedElements.length ? 'Search' : 'Telegram Search';\n this.inputSearch.container.classList.toggle('is-picked-twice', pickedElements.length === 2);\n this.inputSearch.container.classList.toggle('is-picked', !!pickedElements.length);\n\n if(pickedElements.length) {\n this.inputSearch.input.style.setProperty('--paddingLeft', (pickedElements[pickedElements.length - 1].getBoundingClientRect().right - this.inputSearch.input.getBoundingClientRect().left) + 'px');\n } else {\n this.inputSearch.input.style.removeProperty('--paddingLeft');\n }\n };\n\n const helper = document.createElement('div');\n helper.classList.add('search-helper');\n helper.addEventListener('click', (e) => {\n const target = findUpClassName(e.target, 'selector-user');\n if(!target) {\n return;\n }\n\n const key = target.dataset.key;\n if(key.indexOf('date_') === 0) {\n const [_, minDate, maxDate] = key.split('_');\n selectedMinDate = +minDate;\n selectedMaxDate = +maxDate;\n } else {\n selectedPeerId = +key;\n }\n\n target.addEventListener('click', () => {\n unselectEntity(target);\n });\n\n this.inputSearch.container.append(target);\n this.inputSearch.onChange(this.inputSearch.value = '');\n pickedElements.push(target);\n updatePicked();\n });\n\n searchSuper.nav.parentElement.append(helper);\n\n const renderEntity = (peerId: any, title?: string | HTMLElement) => {\n const div = document.createElement('div');\n div.classList.add('selector-user'/* , 'scale-in' */);\n\n const avatarEl = document.createElement('avatar-element');\n avatarEl.classList.add('selector-user-avatar', 'tgico');\n avatarEl.setAttribute('dialog', '1');\n avatarEl.classList.add('avatar-30');\n\n div.dataset.key = '' + peerId;\n if(typeof(peerId) === 'number') {\n if(title === undefined) {\n title = new PeerTitle({peerId, onlyFirstName: true}).element;\n }\n\n avatarEl.setAttribute('peer', '' + peerId);\n } else {\n avatarEl.classList.add('tgico-calendarfilter');\n }\n\n if(title) {\n if(typeof(title) === 'string') {\n div.innerHTML = title;\n } else {\n replaceContent(div, title);\n div.append(title);\n }\n }\n\n div.insertAdjacentElement('afterbegin', avatarEl);\n\n return div;\n };\n\n const unselectEntity = (target: HTMLElement) => {\n const key = target.dataset.key;\n if(key.indexOf('date_') === 0) {\n selectedMinDate = selectedMaxDate = 0;\n } else {\n selectedPeerId = 0;\n }\n \n target.remove();\n pickedElements.findAndSplice(t => t === target);\n\n setTimeout(() => {\n updatePicked();\n this.inputSearch.onChange(this.inputSearch.value);\n }, 0);\n };\n\n this.inputSearch.onClear = () => {\n pickedElements.forEach(el => {\n unselectEntity(el);\n });\n };\n\n this.inputSearch.onChange = (value) => {\n searchSuper.cleanupHTML();\n searchSuper.setQuery({\n peerId: selectedPeerId, \n folderId: selectedPeerId ? undefined : 0,\n query: value,\n minDate: selectedMinDate,\n maxDate: selectedMaxDate\n });\n searchSuper.load(true);\n\n helper.innerHTML = '';\n searchSuper.nav.classList.remove('hide');\n if(!value) {\n }\n \n if(!selectedPeerId && value.trim()) {\n const middleware = searchSuper.middleware.get();\n Promise.all([\n appMessagesManager.getConversationsAll(value).then(dialogs => dialogs.map(d => d.peerId)),\n appUsersManager.getContacts(value, true)\n ]).then(results => {\n if(!middleware()) return;\n const peerIds = new Set(results[0].concat(results[1]));\n \n peerIds.forEach(peerId => {\n helper.append(renderEntity(peerId));\n });\n \n searchSuper.nav.classList.toggle('hide', !!helper.innerHTML);\n //console.log('got peerIds by value:', value, [...peerIds]);\n });\n }\n \n if(!selectedMinDate && value.trim()) {\n const dates: DateData[] = [];\n fillTipDates(value, dates);\n dates.forEach(dateData => {\n helper.append(renderEntity('date_' + dateData.minDate + '_' + dateData.maxDate, dateData.title));\n });\n\n searchSuper.nav.classList.toggle('hide', !!helper.innerHTML);\n }\n };\n\n searchSuper.tabs.inputMessagesFilterEmpty.addEventListener('mousedown', (e) => {\n const target = findUpTag(e.target, 'LI') as HTMLElement;\n if(!target) {\n return;\n }\n\n const searchGroup = findUpClassName(target, 'search-group');\n if(!searchGroup || searchGroup.classList.contains('search-group-recent') || searchGroup.classList.contains('search-group-people')) {\n return;\n }\n\n const peerId = +target.getAttribute('data-peer-id');\n appStateManager.getState().then(state => {\n const recentSearch = state.recentSearch || [];\n if(recentSearch[0] !== peerId) {\n recentSearch.findAndSplice(p => p === peerId);\n recentSearch.unshift(peerId);\n if(recentSearch.length > 20) {\n recentSearch.length = 20;\n }\n \n appStateManager.pushToState('recentSearch', recentSearch);\n for(const peerId of recentSearch) {\n appStateManager.setPeer(peerId, appPeersManager.getPeer(peerId));\n }\n }\n });\n }, {capture: true});\n\n let peopleContainer = document.createElement('div');\n peopleContainer.classList.add('search-group-scrollable');\n peopleContainer.append(this.searchGroups.people.list);\n this.searchGroups.people.container.append(peopleContainer);\n let peopleScrollable = new ScrollableX(peopleContainer);\n\n let hideNewBtnMenuTimeout: number;\n //const transition = Transition.bind(null, searchContainer.parentElement, 150);\n const transition = TransitionSlider(searchContainer.parentElement, 'zoom-fade', 150, (id) => {\n if(hideNewBtnMenuTimeout) clearTimeout(hideNewBtnMenuTimeout);\n\n if(id === 0) {\n searchSuper.selectTab(0, false);\n this.inputSearch.onClearClick();\n hideNewBtnMenuTimeout = window.setTimeout(() => {\n hideNewBtnMenuTimeout = 0;\n this.newBtnMenu.classList.remove('is-hidden');\n }, 150);\n }\n });\n\n transition(0);\n\n const activeClassName = 'is-visible';\n const onFocus = () => {\n this.toolsBtn.classList.remove(activeClassName);\n this.backBtn.classList.add(activeClassName);\n this.newBtnMenu.classList.add('is-hidden');\n this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', true);\n\n if(!isMobileSafari && !appNavigationController.findItemByType('global-search')) {\n appNavigationController.pushItem({\n onPop: () => {\n close();\n },\n type: 'global-search'\n });\n }\n\n transition(1);\n };\n\n this.inputSearch.input.addEventListener('focus', onFocus);\n onFocus();\n\n this.backBtn.addEventListener('click', (e) => {\n this.toolsBtn.classList.add(activeClassName);\n this.backBtn.classList.remove(activeClassName);\n this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', false);\n\n appNavigationController.removeByType('global-search');\n\n transition(0);\n });\n\n const clearRecentSearchBtn = document.createElement('button');\n clearRecentSearchBtn.classList.add('btn-icon', 'tgico-close');\n this.searchGroups.recent.nameEl.append(clearRecentSearchBtn);\n clearRecentSearchBtn.addEventListener('click', () => {\n this.searchGroups.recent.clear();\n appStateManager.pushToState('recentSearch', []);\n });\n }\n}\n\nexport class SettingSection {\n public container: HTMLElement;\n public content: HTMLElement;\n public title: HTMLElement;\n public caption: HTMLElement;\n\n constructor(options: {\n name?: LangPackKey, \n caption?: LangPackKey | true,\n noDelimiter?: boolean\n }) {\n this.container = document.createElement('div');\n this.container.classList.add('sidebar-left-section');\n\n if(!options.noDelimiter) {\n const hr = document.createElement('hr');\n this.container.append(hr);\n } else {\n this.container.classList.add('no-delimiter');\n }\n\n this.content = this.generateContentElement();\n\n if(options.name) {\n this.title = document.createElement('div');\n this.title.classList.add('sidebar-left-h2', 'sidebar-left-section-name');\n i18n_({element: this.title, key: options.name});\n this.content.append(this.title);\n }\n\n if(options.caption) {\n this.caption = this.generateContentElement();\n this.caption.classList.add('sidebar-left-section-caption');\n\n if(options.caption !== true) {\n i18n_({element: this.caption, key: options.caption});\n }\n }\n }\n\n public generateContentElement() {\n const content = document.createElement('div');\n content.classList.add('sidebar-left-section-content');\n this.container.append(content);\n return content;\n }\n}\n\nexport const generateSection = (appendTo: Scrollable, name?: LangPackKey, caption?: LangPackKey) => {\n const section = new SettingSection({name, caption});\n appendTo.append(section.container);\n return section.content;\n};\n\nconst appSidebarLeft = new AppSidebarLeft();\nMOUNT_CLASS_TO.appSidebarLeft = appSidebarLeft;\nexport default appSidebarLeft;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport rootScope from \"../../lib/rootScope\";\n//import { generatePathData } from \"../../helpers/dom\";\nimport { MyMessage } from \"../../lib/appManagers/appMessagesManager\";\nimport type Chat from \"./chat\";\n\ntype Group = {bubble: HTMLElement, mid: number, timestamp: number}[];\ntype BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};\nexport default class BubbleGroups {\n private bubbles: Array<BubbleGroup> = []; // map to group\n private detailsMap: Map<HTMLElement, BubbleGroup> = new Map();\n private groups: Array<Group> = [];\n //updateRAFs: Map<HTMLElement[], number> = new Map();\n private newGroupDiff = 121; // * 121 in scheduled messages\n\n constructor(private chat: Chat) {\n\n }\n\n removeBubble(bubble: HTMLElement) {\n const details = this.detailsMap.get(bubble);\n if(details) {\n if(details.group.length) {\n details.group.findAndSplice(d => d.bubble === bubble);\n if(!details.group.length) {\n this.groups.findAndSplice(g => g === details.group);\n } else {\n this.updateGroup(details.group);\n }\n }\n \n this.detailsMap.delete(bubble);\n }\n }\n \n addBubble(bubble: HTMLElement, message: MyMessage, reverse: boolean) {\n //return;\n\n const timestamp = message.date;\n const mid = message.mid;\n let fromId = message.fromId;\n let group: Group;\n\n // fix for saved messages forward to self\n if(fromId === rootScope.myId && message.peerId === rootScope.myId && (message as any).fwdFromId === fromId) {\n fromId = -fromId;\n }\n \n // try to find added\n this.removeBubble(bubble);\n \n const insertObject = {bubble, mid, timestamp};\n if(this.bubbles.length) {\n let foundBubble: BubbleGroup;\n let foundAtIndex = -1;\n for(let i = 0; i < this.bubbles.length; ++i) {\n const bubble = this.bubbles[i];\n const diff = Math.abs(bubble.timestamp - timestamp);\n const good = bubble.fromId === fromId && diff <= this.newGroupDiff;\n\n if(good) {\n foundAtIndex = i;\n\n if(this.chat.type === 'scheduled') {\n break;\n }\n } else {\n foundAtIndex = -1;\n }\n\n if(this.chat.type !== 'scheduled') {\n if(mid > bubble.mid) {\n break;\n }\n }\n }\n\n if(foundAtIndex !== -1) {\n foundBubble = this.bubbles[foundAtIndex];\n }\n /* const foundBubble = this.bubbles.find(bubble => {\n const diff = Math.abs(bubble.timestamp - timestamp);\n return bubble.fromId === fromId && diff <= this.newGroupDiff;\n }); */\n\n if(!foundBubble) this.groups.push(group = [insertObject]);\n else {\n group = foundBubble.group;\n \n let i = 0, foundMidOnSameTimestamp = 0;\n for(; i < group.length; ++i) {\n const _timestamp = group[i].timestamp;\n const _mid = group[i].mid;\n\n if(timestamp < _timestamp) {\n break;\n } else if(timestamp === _timestamp) {\n foundMidOnSameTimestamp = _mid;\n } \n \n if(foundMidOnSameTimestamp && mid < foundMidOnSameTimestamp) {\n break;\n }\n }\n\n group.splice(i, 0, insertObject);\n }\n } else {\n this.groups.push(group = [insertObject]);\n }\n\n //console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);\n\n const bubbleGroup = {timestamp, fromId, mid: message.mid, group};\n let insertIndex = 0;\n for(; insertIndex < this.bubbles.length; ++insertIndex) {\n if(this.bubbles[insertIndex].mid < mid) {\n break;\n }\n }\n \n this.bubbles.splice(insertIndex, 0, {timestamp, fromId, mid: message.mid, group});\n this.updateGroup(group);\n\n this.detailsMap.set(bubble, bubbleGroup);\n }\n\n /* setClipIfNeeded(bubble: HTMLDivElement, remove = false) {\n //console.log('setClipIfNeeded', bubble, remove);\n const className = bubble.className;\n if(className.includes('is-message-empty') && (className.includes('photo') || className.includes('video'))) {\n let container = bubble.querySelector('.bubble__media-container') as SVGSVGElement;\n //console.log('setClipIfNeeded', bubble, remove, container);\n if(!container) return;\n\n try {\n Array.from(container.children).forEach(object => {\n if(object instanceof SVGDefsElement) return;\n \n if(remove) {\n object.removeAttributeNS(null, 'clip-path');\n } else {\n let clipId = container.dataset.clipId;\n let path = container.firstElementChild.firstElementChild.lastElementChild as SVGPathElement;\n let width = +object.getAttributeNS(null, 'width');\n let height = +object.getAttributeNS(null, 'height');\n let isOut = className.includes('is-out');\n let isReply = className.includes('is-reply');\n let d = '';\n \n //console.log('setClipIfNeeded', object, width, height, isOut);\n \n let tr: number, tl: number;\n if(className.includes('forwarded') || isReply) {\n tr = tl = 0;\n } else if(isOut) {\n tr = className.includes('is-group-first') ? 12 : 6;\n tl = 12;\n } else {\n tr = 12;\n tl = className.includes('is-group-first') ? 12 : 6;\n }\n \n if(isOut) {\n d = generatePathData(0, 0, width - 9, height, tl, tr, 0, 12);\n } else {\n d = generatePathData(9, 0, width - 9, height, tl, tr, 12, 0);\n }\n \n path.setAttributeNS(null, 'd', d);\n object.setAttributeNS(null, 'clip-path', 'url(#' + clipId + ')');\n }\n });\n } catch(err) {}\n }\n } */\n \n updateGroup(group: Group) {\n /* if(this.updateRAFs.has(group)) {\n window.cancelAnimationFrame(this.updateRAFs.get(group));\n this.updateRAFs.delete(group);\n } */\n \n //this.updateRAFs.set(group, window.requestAnimationFrame(() => {\n //this.updateRAFs.delete(group);\n \n if(!group.length) {\n return;\n }\n \n const first = group[0].bubble;\n\n //console.log('[BUBBLE]: updateGroup', group, first);\n \n if(group.length === 1) {\n first.classList.add('is-group-first', 'is-group-last');\n //this.setClipIfNeeded(first);\n return;\n } else {\n first.classList.remove('is-group-last');\n first.classList.add('is-group-first');\n //this.setClipIfNeeded(first, true);\n }\n \n const length = group.length - 1;\n for(let i = 1; i < length; ++i) {\n const bubble = group[i].bubble;\n bubble.classList.remove('is-group-last', 'is-group-first');\n //this.setClipIfNeeded(bubble, true);\n }\n \n const last = group[group.length - 1].bubble;\n last.classList.remove('is-group-first');\n last.classList.add('is-group-last');\n //this.setClipIfNeeded(last);\n //}));\n }\n\n updateGroupByMessageId(mid: number) {\n const details = this.bubbles.find(g => g.mid === mid);\n if(details) {\n this.updateGroup(details.group);\n }\n }\n \n cleanup() {\n this.bubbles = [];\n this.groups = [];\n this.detailsMap.clear();\n /* for(let value of this.updateRAFs.values()) {\n window.cancelAnimationFrame(value);\n }\n this.updateRAFs.clear(); */\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport PopupElement, { PopupOptions } from \".\";\nimport mediaSizes from \"../../helpers/mediaSizes\";\nimport I18n, { i18n, LangPackKey } from \"../../lib/langPack\";\nimport InputField from \"../inputField\";\n\nexport default class PopupDatePicker extends PopupElement {\n protected controlsDiv: HTMLElement;\n protected monthTitle: HTMLElement;\n protected prevBtn: HTMLElement;\n protected nextBtn: HTMLElement;\n\n protected monthsContainer: HTMLElement;\n protected month: HTMLElement;\n\n protected minMonth: Date;\n protected maxMonth: Date;\n protected minDate: Date;\n protected maxDate: Date;\n protected selectedDate: Date;\n protected selectedMonth: Date;\n protected selectedEl: HTMLElement;\n\n protected timeDiv: HTMLDivElement;\n protected hoursInputField: InputField;\n protected minutesInputField: InputField;\n\n constructor(initDate: Date, public onPick: (timestamp: number) => void, protected options: Partial<{\n noButtons: true, \n noTitle: true, \n minDate: Date,\n maxDate: Date\n withTime: true,\n showOverflowMonths: true\n }> & PopupOptions = {}) {\n super('popup-date-picker', options.noButtons ? [] : [{\n langKey: 'JumpToDate',\n callback: () => {\n if(this.onPick) {\n this.onPick(this.selectedDate.getTime() / 1000 | 0);\n }\n }\n }, {\n langKey: 'Cancel',\n isCancel: true\n }], {body: true, overlayClosable: true, ...options});\n\n this.minDate = options.minDate || new Date('2013-08-01T00:00:00');\n\n if(initDate < this.minDate) {\n initDate.setFullYear(this.minDate.getFullYear(), this.minDate.getMonth(), this.minDate.getDate());\n }\n\n // Controls\n this.controlsDiv = document.createElement('div');\n this.controlsDiv.classList.add('date-picker-controls');\n\n this.prevBtn = document.createElement('button');\n this.prevBtn.classList.add('btn-icon', 'tgico-down', 'date-picker-prev');\n this.prevBtn.addEventListener('click', this.onPrevClick);\n\n this.nextBtn = document.createElement('button');\n this.nextBtn.classList.add('btn-icon', 'tgico-down', 'date-picker-next');\n this.nextBtn.addEventListener('click', this.onNextClick);\n \n this.monthTitle = document.createElement('div');\n this.monthTitle.classList.add('date-picker-month-title');\n\n this.controlsDiv.append(this.prevBtn, this.monthTitle, this.nextBtn);\n\n // Month\n this.monthsContainer = document.createElement('div');\n this.monthsContainer.classList.add('date-picker-months');\n this.monthsContainer.addEventListener('click', this.onDateClick);\n\n this.body.append(this.controlsDiv, this.monthsContainer);\n\n // Time inputs\n if(options.withTime) {\n this.timeDiv = document.createElement('div');\n this.timeDiv.classList.add('date-picker-time');\n\n const delimiter = document.createElement('div');\n delimiter.classList.add('date-picker-time-delimiter');\n delimiter.append(':');\n\n const handleTimeInput = (max: number, inputField: InputField, onInput: (length: number) => void, onOverflow?: (number: number) => void) => {\n const maxString = '' + max;\n inputField.input.addEventListener('input', (e) => {\n let value = inputField.value.replace(/\\D/g, '');\n if(value.length > 2) {\n value = value.slice(0, 2);\n } else {\n if((value.length === 1 && +value[0] > +maxString[0]) || (value.length === 2 && +value > max)) {\n if(value.length === 2 && onOverflow) {\n onOverflow(+value[1]);\n }\n\n value = '0' + value[0];\n }\n }\n\n inputField.setValueSilently(value);\n onInput(value.length);\n });\n };\n\n this.hoursInputField = new InputField({plainText: true});\n this.minutesInputField = new InputField({plainText: true});\n\n handleTimeInput(23, this.hoursInputField, (length) => {\n if(length === 2) {\n this.minutesInputField.input.focus();\n }\n\n this.setTimeTitle();\n }, (number) => {\n this.minutesInputField.value = (number + this.minutesInputField.value).slice(0, 2);\n });\n handleTimeInput(59, this.minutesInputField, (length) => {\n if(!length) {\n this.hoursInputField.input.focus();\n }\n\n this.setTimeTitle();\n });\n\n this.selectedDate = initDate;\n\n initDate.setMinutes(initDate.getMinutes() + 10);\n \n this.hoursInputField.setValueSilently(('0' + initDate.getHours()).slice(-2));\n this.minutesInputField.setValueSilently(('0' + initDate.getMinutes()).slice(-2));\n\n initDate.setHours(0, 0, 0, 0);\n \n this.timeDiv.append(this.hoursInputField.container, delimiter, this.minutesInputField.container);\n\n this.btnConfirm.addEventListener('click', () => {\n if(this.onPick) {\n this.selectedDate.setHours(+this.hoursInputField.value || 0, +this.minutesInputField.value || 0, 0, 0);\n this.onPick(this.selectedDate.getTime() / 1000 | 0);\n }\n\n this.hide();\n }, {once: true});\n\n this.body.append(this.timeDiv);\n\n this.prevBtn.classList.add('primary');\n this.nextBtn.classList.add('primary');\n }\n\n const popupCenterer = document.createElement('div');\n popupCenterer.classList.add('popup-centerer');\n popupCenterer.append(this.container);\n this.element.append(popupCenterer);\n\n //const passed = (initDate.getTime() - (initDate.getTimezoneOffset() * 60000)) % 86400000;\n //this.selectedDate = this.maxDate = new Date(initDate.getTime() - passed);\n initDate.setHours(0, 0, 0, 0);\n this.selectedDate = initDate;\n\n this.maxDate = options.maxDate || new Date();\n this.maxDate.setHours(0, 0, 0, 0);\n\n this.selectedMonth = new Date(this.selectedDate);\n this.selectedMonth.setDate(1);\n\n this.maxMonth = new Date(this.maxDate);\n this.maxMonth.setDate(1);\n\n this.minMonth = new Date(this.minDate);\n this.minMonth.setHours(0, 0, 0, 0);\n this.minMonth.setDate(1);\n\n if(this.selectedMonth.getTime() === this.minMonth.getTime()) {\n this.prevBtn.setAttribute('disabled', 'true');\n }\n\n if(this.selectedMonth.getTime() === this.maxMonth.getTime()) {\n this.nextBtn.setAttribute('disabled', 'true');\n }\n\n if(options.noTitle) {\n this.setTitle = () => {};\n }\n\n this.setTimeTitle();\n this.setTitle();\n this.setMonth();\n }\n\n onPrevClick = (e: MouseEvent) => {\n this.selectedMonth.setMonth(this.selectedMonth.getMonth() - 1);\n this.setMonth();\n\n if(this.selectedMonth.getTime() === this.minMonth.getTime()) {\n this.prevBtn.setAttribute('disabled', 'true');\n }\n \n this.nextBtn.removeAttribute('disabled');\n };\n\n onNextClick = (e: MouseEvent) => {\n this.selectedMonth.setMonth(this.selectedMonth.getMonth() + 1);\n this.setMonth();\n\n if(this.selectedMonth.getTime() === this.maxMonth.getTime()) {\n this.nextBtn.setAttribute('disabled', 'true');\n }\n\n this.prevBtn.removeAttribute('disabled');\n };\n\n onDateClick = (e: MouseEvent) => {\n //cancelEvent(e);\n const target = e.target as HTMLElement;\n\n if(!target.dataset.timestamp) return;\n\n if(this.selectedEl) {\n if(this.selectedEl === target) return;\n this.selectedEl.classList.remove('active');\n }\n\n this.selectedEl = target;\n \n target.classList.add('active');\n const timestamp = +target.dataset.timestamp;\n\n this.selectedDate = new Date(timestamp);\n\n this.setTitle();\n this.setTimeTitle();\n };\n\n public setTimeTitle() {\n if(this.btnConfirm && this.selectedDate) {\n let key: LangPackKey, args: any[] = [];\n const date = new Date();\n date.setHours(0, 0, 0, 0);\n\n const timeOptions: Intl.DateTimeFormatOptions = {\n minute: '2-digit',\n hour: '2-digit'\n };\n \n const sendDate = new Date(this.selectedDate.getTime());\n sendDate.setHours(+this.hoursInputField.value, +this.minutesInputField.value);\n\n if(this.selectedDate.getTime() === date.getTime()) {\n key = 'Schedule.SendToday';\n }/* else if(this.selectedDate.getTime() === (date.getTime() + 86400e3)) {\n dayStr = 'Tomorrow';\n } */ else {\n key = 'Schedule.SendDate';\n\n const dateOptions: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric'\n };\n\n if(sendDate.getFullYear() !== date.getFullYear()) {\n dateOptions.year = 'numeric';\n }\n\n args.push(new I18n.IntlDateElement({\n date: sendDate,\n options: dateOptions\n }).element);\n }\n\n args.push(new I18n.IntlDateElement({\n date: sendDate,\n options: timeOptions\n }).element);\n\n this.btnConfirm.firstChild.replaceWith(i18n(key, args));\n }\n }\n\n public setTitle() {\n //const splitted = this.selectedDate.toString().split(' ', 3);\n //this.title.innerText = splitted[0] + ', ' + splitted[1] + ' ' + splitted[2];\n this.title.textContent = '';\n this.title.append(new I18n.IntlDateElement({\n date: this.selectedDate,\n options: {\n day: 'numeric',\n month: 'long',\n weekday: 'short'\n }\n }).element);\n }\n\n private renderElement(disabled: boolean, innerText: string | HTMLElement = '') {\n const el = document.createElement('button');\n el.classList.add('btn-icon', 'date-picker-month-date');\n\n if(disabled) {\n el.setAttribute('disabled', 'true');\n }\n\n if(innerText) {\n el.append(innerText);\n }\n\n return el;\n }\n\n public setMonth() {\n const firstDate = new Date(this.selectedMonth);\n\n const options: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: this.timeDiv && mediaSizes.isMobile ? 'short' : 'long'\n };\n\n this.monthTitle.textContent = '';\n this.monthTitle.append(new I18n.IntlDateElement({date: firstDate, options}).element);\n //this.monthTitle.innerText = (this.timeDiv && mediaSizes.isMobile ? monthName.slice(0, 3) : monthName) + ' ' + this.selectedMonth.getFullYear();\n\n if(this.month) {\n this.month.remove();\n }\n\n this.month = document.createElement('div');\n this.month.classList.add('date-picker-month');\n\n const weekStartDate = new Date();\n const day = weekStartDate.getDay();\n if(day !== 1) {\n weekStartDate.setHours(-24 * (day - 1)); \n }\n\n for(let i = 0; i < 7; ++i) {\n const el = this.renderElement(true, new I18n.IntlDateElement({date: weekStartDate, options: {weekday: 'narrow'}}).element);\n el.classList.remove('date-picker-month-date');\n el.classList.add('date-picker-month-day');\n this.month.append(el);\n weekStartDate.setDate(weekStartDate.getDate() + 1);\n }\n\n // 0 - sunday\n let dayIndex = firstDate.getDay() - 1;\n if(dayIndex === -1) dayIndex = 7 - 1;\n\n const clonedDate = new Date(firstDate.getTime());\n clonedDate.setDate(clonedDate.getDate() - dayIndex - 1);\n\n // Padding first week\n for(let i = 0; i < dayIndex; ++i) {\n if(this.options.showOverflowMonths) {\n clonedDate.setDate(clonedDate.getDate() + 1);\n this.month.append(this.renderElement(true, '' + clonedDate.getDate()));\n } else {\n this.month.append(this.renderElement(true));\n }\n }\n\n do {\n const date = firstDate.getDate();\n const el = this.renderElement(firstDate > this.maxDate || firstDate < this.minDate, '' + date);\n el.dataset.timestamp = '' + firstDate.getTime();\n\n if(firstDate.getTime() === this.selectedDate.getTime()) {\n this.selectedEl = el;\n el.classList.add('active');\n }\n\n this.month.append(el);\n\n firstDate.setDate(date + 1);\n } while(firstDate.getDate() !== 1);\n\n const remainder = this.month.childElementCount % 7;\n if(this.options.showOverflowMonths && remainder) {\n for(let i = remainder; i < 7; ++i) {\n this.month.append(this.renderElement(true, '' + firstDate.getDate()));\n firstDate.setDate(firstDate.getDate() + 1);\n }\n }\n\n const lines = Math.ceil(this.month.childElementCount / 7);\n this.container.dataset.lines = '' + lines;\n\n this.monthsContainer.append(this.month);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appImManager from \"../../lib/appManagers/appImManager\";\nimport PopupPickUser from \"./pickUser\";\n\nexport default class PopupForward extends PopupPickUser {\n constructor(fromPeerId: number, mids: number[], onSelect?: () => Promise<void> | void, onClose?: () => void) {\n super({\n peerTypes: ['dialogs', 'contacts'],\n onSelect: async(peerId) => {\n if(onSelect) {\n const res = onSelect();\n if(res instanceof Promise) {\n await res;\n }\n }\n\n appImManager.setInnerPeer(peerId);\n appImManager.chat.input.initMessagesForward(fromPeerId, mids.slice());\n },\n onClose,\n placeholder: 'ShareModal.Search.ForwardPlaceholder',\n chatRightsAction: 'send_messages'\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport PopupElement from \".\";\nimport appStickersManager from \"../../lib/appManagers/appStickersManager\";\nimport { RichTextProcessor } from \"../../lib/richtextprocessor\";\nimport Scrollable from \"../scrollable\";\nimport { wrapSticker } from \"../wrappers\";\nimport LazyLoadQueue from \"../lazyLoadQueue\";\nimport { putPreloader } from \"../misc\";\nimport animationIntersector from \"../animationIntersector\";\nimport { toggleDisability } from \"../../helpers/dom\";\nimport appImManager from \"../../lib/appManagers/appImManager\";\nimport { StickerSet } from \"../../layer\";\nimport mediaSizes from \"../../helpers/mediaSizes\";\nimport { i18n } from \"../../lib/langPack\";\nimport Button from \"../button\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\n\nconst ANIMATION_GROUP = 'STICKERS-POPUP';\n\nexport default class PopupStickers extends PopupElement {\n private stickersFooter: HTMLElement;\n private stickersDiv: HTMLElement;\n private h6: HTMLElement;\n\n private set: StickerSet.stickerSet;\n\n constructor(private stickerSetInput: {\n //_: 'inputStickerSetID',\n id: string,\n access_hash: string\n }) {\n super('popup-stickers', null, {closable: true, overlayClosable: true, body: true});\n\n this.h6 = document.createElement('h6');\n this.h6.append(i18n('Loading'));\n\n this.header.append(this.h6);\n\n this.onClose = () => {\n animationIntersector.setOnlyOnePlayableGroup('');\n this.stickersFooter.removeEventListener('click', this.onFooterClick);\n this.stickersDiv.removeEventListener('click', this.onStickersClick);\n };\n\n const div = document.createElement('div');\n div.classList.add('sticker-set');\n\n this.stickersDiv = document.createElement('div');\n this.stickersDiv.classList.add('sticker-set-stickers', 'is-loading');\n\n putPreloader(this.stickersDiv, true);\n\n this.stickersFooter = document.createElement('div');\n this.stickersFooter.classList.add('sticker-set-footer');\n\n div.append(this.stickersDiv);\n\n const btn = Button('btn-primary btn-primary-transparent disable-hover', {noRipple: true, text: 'Loading'});\n this.stickersFooter.append(btn);\n\n this.body.append(div);\n const scrollable = new Scrollable(this.body);\n this.body.append(this.stickersFooter);\n \n // const editButton = document.createElement('button');\n // editButton.classList.add('btn-primary');\n\n // this.stickersFooter.append(editButton);\n\n this.loadStickerSet();\n }\n\n onFooterClick = () => {\n const toggle = toggleDisability([this.stickersFooter], true);\n\n appStickersManager.toggleStickerSet(this.set).then(() => {\n this.hide();\n }).catch(() => {\n toggle();\n });\n };\n\n onStickersClick = (e: MouseEvent) => {\n const target = findUpClassName(e.target, 'sticker-set-sticker');\n if(!target) return;\n\n const fileId = target.dataset.docId;\n if(appImManager.chat.input.sendMessageWithDocument(fileId)) {\n this.hide();\n } else {\n console.warn('got no doc by id:', fileId);\n }\n };\n\n private loadStickerSet() {\n return appStickersManager.getStickerSet(this.stickerSetInput).then(set => {\n //console.log('PopupStickers loadStickerSet got set:', set);\n\n this.set = set.set;\n\n animationIntersector.setOnlyOnePlayableGroup(ANIMATION_GROUP);\n\n this.h6.innerHTML = RichTextProcessor.wrapEmojiText(set.set.title);\n this.stickersFooter.classList.toggle('add', !set.set.installed_date);\n\n let button: HTMLElement;\n if(set.set.installed_date) {\n button = Button('btn-primary btn-primary-transparent danger', {noRipple: true});\n button.append(i18n('RemoveStickersCount', [i18n('Stickers', [set.set.count])]));\n } else {\n button = Button('btn-primary btn-color-primary', {noRipple: true});\n button.append(i18n('AddStickersCount', [i18n('Stickers', [set.set.count])]));\n }\n\n this.stickersFooter.textContent = '';\n this.stickersFooter.append(button);\n\n button.addEventListener('click', this.onFooterClick);\n\n if(set.documents.length) {\n this.stickersDiv.addEventListener('click', this.onStickersClick);\n }\n\n const lazyLoadQueue = new LazyLoadQueue();\n \n this.stickersDiv.classList.remove('is-loading');\n this.stickersDiv.innerHTML = '';\n for(let doc of set.documents) {\n if(doc._ === 'documentEmpty') {\n continue;\n }\n \n const div = document.createElement('div');\n div.classList.add('sticker-set-sticker');\n\n const size = mediaSizes.active.esgSticker.width;\n \n wrapSticker({\n doc, \n div, \n lazyLoadQueue, \n group: ANIMATION_GROUP, \n play: true,\n loop: true,\n width: size,\n height: size\n });\n\n this.stickersDiv.append(div);\n }\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nexport default class StickyIntersector {\n private headersObserver: IntersectionObserver;\n private elementsObserver: IntersectionObserver;\n\n constructor(private container: HTMLElement, private handler: (stuck: boolean, target: HTMLElement) => void) {\n this.observeHeaders();\n this.observeElements();\n }\n\n /**\n * Sets up an intersection observer to notify when elements with the class\n * `.sticky_sentinel--top` become visible/invisible at the top of the container.\n * @param {!Element} container\n */\n private observeHeaders() {\n this.headersObserver = new IntersectionObserver((entries) => {\n for(const entry of entries) {\n const targetInfo = entry.boundingClientRect;\n const stickyTarget = entry.target.parentElement;\n const rootBoundsInfo = entry.rootBounds;\n \n // Started sticking.\n if(targetInfo.bottom < rootBoundsInfo.top) {\n this.handler(true, stickyTarget);\n }\n \n // Stopped sticking.\n if(targetInfo.bottom >= rootBoundsInfo.top &&\n targetInfo.bottom < rootBoundsInfo.bottom) {\n this.handler(false, stickyTarget);\n }\n }\n }, {threshold: 0, root: this.container});\n }\n \n private observeElements() {\n this.elementsObserver = new IntersectionObserver((entries) => {\n let entry = entries.filter(entry => entry.boundingClientRect.top < 0).sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];\n if(!entry) return;\n let container = entry.isIntersecting ? entry.target : entry.target.nextElementSibling;\n this.handler(true, container as HTMLElement);\n }, {root: this.container});\n }\n\n /**\n * @param {!Element} container\n * @param {string} className\n */\n private addSentinel(container: HTMLElement, className: string) {\n const sentinel = document.createElement('div');\n sentinel.classList.add('sticky_sentinel', className);\n return container.appendChild(sentinel);\n }\n\n /**\n * Notifies when elements w/ the `sticky` class begin to stick or stop sticking.\n * Note: the elements should be children of `container`.\n * @param {!Element} container\n */\n public observeStickyHeaderChanges(element: HTMLElement) {\n const headerSentinel = this.addSentinel(element, 'sticky_sentinel--top');\n this.headersObserver.observe(headerSentinel);\n\n this.elementsObserver.observe(element);\n }\n\n public disconnect() {\n this.headersObserver.disconnect();\n this.elementsObserver.disconnect();\n }\n\n public unobserve(element: HTMLElement, headerSentinel: HTMLElement) {\n this.elementsObserver.unobserve(element);\n this.headersObserver.unobserve(headerSentinel);\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { formatNumber } from \"../../helpers/number\";\nimport { Message } from \"../../layer\";\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../../lib/appManagers/appPeersManager\";\nimport rootScope from \"../../lib/rootScope\";\nimport { ripple } from \"../ripple\";\nimport AvatarElement from \"../avatar\";\n\nconst TAG_NAME = 'replies-element';\n\nrootScope.on('replies_updated', (e) => {\n const message = e;\n (Array.from(document.querySelectorAll(TAG_NAME + `[data-post-key=\"${message.peerId}_${message.mid}\"]`)) as RepliesElement[]).forEach(element => {\n element.message = message;\n element.render();\n });\n});\n\nexport default class RepliesElement extends HTMLElement {\n public message: Message.message;\n public type: 'footer' | 'beside';\n public loadPromises: Promise<any>[];\n \n private updated = false;\n\n constructor() {\n super();\n }\n\n public init() {\n this.render();\n this.dataset.postKey = this.message.peerId + '_' + this.message.mid;\n this.classList.add('replies', 'replies-' + this.type);\n }\n\n public render() {\n const replies = this.message.replies;\n\n /* if(this.firstChild) {\n this.innerHTML = '';\n } */\n\n if(this.type === 'footer') {\n let leftPart: HTMLElement;\n if(this.firstElementChild) {\n leftPart = this.firstElementChild as HTMLElement;\n }\n\n if(replies?.recent_repliers) {\n if(leftPart && !leftPart.classList.contains('replies-footer-avatars')) {\n this.innerHTML = '';\n leftPart = null;\n }\n\n if(!leftPart) {\n leftPart = document.createElement('div');\n leftPart.classList.add('replies-footer-avatars');\n }\n\n replies.recent_repliers.slice().reverse().forEach((peer, idx) => {\n let avatarElem = leftPart.children[idx] as AvatarElement;\n if(!avatarElem) {\n avatarElem = new AvatarElement();\n avatarElem.setAttribute('dialog', '0');\n avatarElem.classList.add('avatar-30');\n \n if(this.loadPromises) {\n avatarElem.loadPromises = this.loadPromises;\n }\n }\n \n avatarElem.setAttribute('peer', '' + appPeersManager.getPeerId(peer));\n \n if(!avatarElem.parentNode) {\n leftPart.append(avatarElem);\n }\n });\n\n // if were 3 and became 2\n (Array.from(leftPart.children) as HTMLElement[]).slice(replies.recent_repliers.length).forEach(el => el.remove());\n } else {\n if(leftPart && !leftPart.classList.contains('tgico-comments')) {\n leftPart.remove();\n leftPart = null;\n }\n\n if(!leftPart) {\n leftPart = document.createElement('span');\n leftPart.classList.add('tgico-comments');\n }\n }\n\n if(!leftPart.parentElement) {\n this.append(leftPart);\n }\n \n let text: string;\n if(replies) {\n if(replies.replies) {\n text = replies.replies + ' ' + (replies.replies > 1 ? 'Comments' : 'Comment');\n } else {\n text = 'Leave a Comment';\n }\n } else {\n text = 'View in chat';\n }\n\n if(replies) {\n const historyStorage = appMessagesManager.getHistoryStorage(-replies.channel_id);\n this.classList.toggle('is-unread', replies.read_max_id < replies.max_id && (!historyStorage.readMaxId || historyStorage.readMaxId < replies.max_id));\n }\n\n let textSpan = this.children[1] as HTMLElement;\n if(!textSpan) {\n textSpan = document.createElement('span');\n textSpan.classList.add('replies-footer-text');\n\n const iconSpan = document.createElement('span');\n iconSpan.classList.add('tgico-next');\n\n const rippleContainer = document.createElement('div');\n ripple(rippleContainer);\n\n this.append(textSpan, iconSpan, rippleContainer);\n }\n\n textSpan.innerHTML = text;\n } else {\n this.classList.add('bubble-beside-button');\n this.innerHTML = `<span class=\"tgico-commentssticker\"></span><span class=\"replies-beside-text\">${replies?.replies ? formatNumber(replies.replies, 0) : ''}</span>`;\n }\n\n if(replies && !this.updated && !this.message.pFlags.is_outgoing) {\n appMessagesManager.subscribeRepliesThread(this.message.peerId, this.message.mid);\n appMessagesManager.updateMessage(this.message.peerId, this.message.mid, 'replies_updated');\n this.updated = true;\n }\n\n if(this.loadPromises) {\n this.loadPromises = undefined;\n }\n }\n}\n\ncustomElements.define(TAG_NAME, RepliesElement);\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { getFullDate } from \"../../helpers/date\";\nimport { formatNumber } from \"../../helpers/number\";\nimport RichTextProcessor from \"../../lib/richtextprocessor\";\nimport { wrapReply } from \"../wrappers\";\nimport Chat from \"./chat\";\nimport RepliesElement from \"./replies\";\n\nexport namespace MessageRender {\n /* export const setText = () => {\n\n }; */\n\n export const setTime = (chat: Chat, message: any, bubble: HTMLElement, bubbleContainer: HTMLElement, messageDiv: HTMLElement) => {\n const date = new Date(message.date * 1000);\n let time = ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);\n\n if(message.views) {\n const postAuthor = message.post_author || message.fwd_from?.post_author;\n\n bubble.classList.add('channel-post');\n time = formatNumber(message.views, 1) + ' <i class=\"tgico-channelviews time-icon\"></i> ' + (postAuthor ? RichTextProcessor.wrapEmojiText(postAuthor) + ', ' : '') + time;\n \n if(!message.fwd_from?.saved_from_msg_id) {\n const forward = document.createElement('div');\n forward.classList.add('bubble-beside-button', 'forward');\n forward.innerHTML = `\n <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 24 24\">\n <defs>\n <path d=\"M13.55 3.24L13.64 3.25L13.73 3.27L13.81 3.29L13.9 3.32L13.98 3.35L14.06 3.39L14.14 3.43L14.22 3.48L14.29 3.53L14.36 3.59L14.43 3.64L22.23 10.85L22.36 10.99L22.48 11.15L22.57 11.31L22.64 11.48L22.69 11.66L22.72 11.85L22.73 12.04L22.71 12.22L22.67 12.41L22.61 12.59L22.53 12.76L22.42 12.93L22.29 13.09L22.23 13.15L14.43 20.36L14.28 20.48L14.12 20.58L13.95 20.66L13.77 20.72L13.58 20.76L13.4 20.77L13.22 20.76L13.03 20.73L12.85 20.68L12.68 20.61L12.52 20.52L12.36 20.4L12.22 20.27L12.16 20.2L12.1 20.13L12.05 20.05L12.01 19.98L11.96 19.9L11.93 19.82L11.89 19.73L11.87 19.65L11.84 19.56L11.83 19.47L11.81 19.39L11.81 19.3L11.8 19.2L11.8 16.42L11 16.49L10.23 16.58L9.51 16.71L8.82 16.88L8.18 17.09L7.57 17.33L7.01 17.6L6.48 17.91L5.99 18.26L5.55 18.64L5.14 19.05L4.77 19.51L4.43 19.99L4.29 20.23L4.21 20.35L4.11 20.47L4 20.57L3.88 20.65L3.75 20.72L3.62 20.78L3.48 20.82L3.33 20.84L3.19 20.84L3.04 20.83L2.9 20.79L2.75 20.74L2.62 20.68L2.53 20.62L2.45 20.56L2.38 20.5L2.31 20.43L2.25 20.36L2.2 20.28L2.15 20.19L2.11 20.11L2.07 20.02L2.04 19.92L2.02 19.83L2.01 19.73L2 19.63L2.04 17.99L2.19 16.46L2.46 15.05L2.85 13.75L3.35 12.58L3.97 11.53L4.7 10.6L5.55 9.8L6.51 9.12L7.59 8.56L8.77 8.13L10.07 7.83L11.48 7.65L11.8 7.63L11.8 4.8L11.91 4.56L12.02 4.35L12.14 4.16L12.25 3.98L12.37 3.82L12.48 3.68L12.61 3.56L12.73 3.46L12.85 3.38L12.98 3.31L13.11 3.27L13.24 3.24L13.37 3.23L13.46 3.23L13.55 3.24Z\" id=\"b13RmHDQtl\"></path>\n </defs>\n <use xlink:href=\"#b13RmHDQtl\" opacity=\"1\" fill=\"#fff\" fill-opacity=\"1\"></use>\n </svg>`;\n bubbleContainer.append(forward);\n bubble.classList.add('with-beside-button');\n }\n }\n\n if(message.edit_date && chat.type !== 'scheduled' && !message.pFlags.edit_hide) {\n bubble.classList.add('is-edited');\n time = '<i class=\"edited\">edited</i> ' + time;\n }\n\n if(chat.type !== 'pinned' && message.pFlags.pinned) {\n bubble.classList.add('is-pinned');\n time = '<i class=\"tgico-pinnedchat time-icon\"></i>' + time;\n }\n\n const title = getFullDate(date) \n + (message.edit_date ? `\\nEdited: ${getFullDate(new Date(message.edit_date * 1000))}` : '')\n + (message.fwd_from ? `\\nOriginal: ${getFullDate(new Date(message.fwd_from.date * 1000))}` : '');\n\n const timeSpan = document.createElement('span');\n timeSpan.classList.add('time', 'tgico');\n timeSpan.title = title;\n timeSpan.innerHTML = `${time}<div class=\"inner tgico\" title=\"${title}\">${time}</div>`;\n\n messageDiv.append(timeSpan);\n\n return timeSpan;\n };\n\n export const renderReplies = ({bubble, bubbleContainer, message, messageDiv, loadPromises}: {\n bubble: HTMLElement,\n bubbleContainer: HTMLElement,\n message: any,\n messageDiv: HTMLElement,\n loadPromises?: Promise<any>[]\n }) => {\n const isFooter = !bubble.classList.contains('sticker') && !bubble.classList.contains('emoji-big') && !bubble.classList.contains('round');\n const repliesFooter = new RepliesElement();\n repliesFooter.message = message;\n repliesFooter.type = isFooter ? 'footer' : 'beside';\n repliesFooter.loadPromises = loadPromises;\n repliesFooter.init();\n bubbleContainer.prepend(repliesFooter);\n return isFooter;\n };\n\n export const setReply = ({chat, bubble, bubbleContainer, message}: {\n chat: Chat,\n bubble: HTMLElement,\n bubbleContainer?: HTMLElement,\n message: any\n }) => {\n const isReplacing = !bubbleContainer;\n if(isReplacing) {\n bubbleContainer = bubble.querySelector('.bubble-content');\n }\n\n const currentReplyDiv = isReplacing ? bubbleContainer.querySelector('.reply') : null;\n if(!message.reply_to_mid) {\n if(currentReplyDiv) {\n currentReplyDiv.remove();\n }\n\n bubble.classList.remove('is-reply');\n return;\n }\n\n\n const replyToPeerId = message.reply_to.reply_to_peer_id ? chat.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : chat.peerId;\n\n let originalMessage = chat.appMessagesManager.getMessageByPeer(replyToPeerId, message.reply_to_mid);\n let originalPeerTitle: string;\n \n /////////this.log('message to render reply', originalMessage, originalPeerTitle, bubble, message);\n \n // need to download separately\n if(originalMessage._ === 'messageEmpty') {\n //////////this.log('message to render reply empty, need download', message, message.reply_to_mid);\n chat.appMessagesManager.wrapSingleMessage(replyToPeerId, message.reply_to_mid);\n chat.bubbles.needUpdate.push({replyToPeerId, replyMid: message.reply_to_mid, mid: message.mid});\n \n originalPeerTitle = 'Loading...';\n } else {\n originalPeerTitle = chat.appPeersManager.getPeerTitle(originalMessage.fromId || originalMessage.fwdFromId, true) || '';\n }\n\n const wrapped = wrapReply(originalPeerTitle, originalMessage.message || '', originalMessage);\n if(currentReplyDiv) {\n currentReplyDiv.replaceWith(wrapped);\n } else {\n bubbleContainer.append(wrapped);\n }\n //bubbleContainer.insertBefore(, nameContainer);\n bubble.classList.add('is-reply');\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\n\nexport function getElementByPoint(container: HTMLElement, verticalSide: 'top' | 'bottom', horizontalSide: 'center' | 'left'): HTMLElement {\n //return null;\n const rect = container.getBoundingClientRect();\n const x = horizontalSide === 'center' ? Math.ceil(rect.left + ((rect.right - rect.left) / 2) + 1) : Math.ceil(rect.left + 1);\n const y = verticalSide === 'bottom' ? Math.floor(rect.top + rect.height - 1) : Math.ceil(rect.top + 1);\n return document.elementFromPoint(x, y) as any;\n};\n\nMOUNT_CLASS_TO.getElementByPoint = getElementByPoint;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppImManager } from \"../../lib/appManagers/appImManager\";\nimport type { AppMessagesManager, HistoryResult, MyMessage } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppStickersManager } from \"../../lib/appManagers/appStickersManager\";\nimport type { AppUsersManager } from \"../../lib/appManagers/appUsersManager\";\nimport type { AppInlineBotsManager } from \"../../lib/appManagers/appInlineBotsManager\";\nimport type { AppPhotosManager } from \"../../lib/appManagers/appPhotosManager\";\nimport type { AppDocsManager } from \"../../lib/appManagers/appDocsManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type sessionStorage from '../../lib/sessionStorage';\nimport type Chat from \"./chat\";\nimport { CHAT_ANIMATION_GROUP } from \"../../lib/appManagers/appImManager\";\nimport { cancelEvent, whichChild, attachClickEvent, positionElementByIndex, reflowScrollableElement, replaceContent } from \"../../helpers/dom\";\nimport { getObjectKeysAndSort } from \"../../helpers/object\";\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport { logger } from \"../../lib/logger\";\nimport rootScope from \"../../lib/rootScope\";\nimport AppMediaViewer from \"../appMediaViewer\";\nimport BubbleGroups from \"./bubbleGroups\";\nimport PopupDatePicker from \"../popups/datePicker\";\nimport PopupForward from \"../popups/forward\";\nimport PopupStickers from \"../popups/stickers\";\nimport ProgressivePreloader from \"../preloader\";\nimport Scrollable from \"../scrollable\";\nimport StickyIntersector from \"../stickyIntersector\";\nimport animationIntersector from \"../animationIntersector\";\nimport RichTextProcessor from \"../../lib/richtextprocessor\";\nimport mediaSizes from \"../../helpers/mediaSizes\";\nimport { isAndroid, isApple, isSafari } from \"../../helpers/userAgent\";\nimport I18n, { i18n, langPack } from \"../../lib/langPack\";\nimport AvatarElement from \"../avatar\";\nimport { formatPhoneNumber } from \"../misc\";\nimport { ripple } from \"../ripple\";\nimport { wrapAlbum, wrapPhoto, wrapVideo, wrapDocument, wrapSticker, wrapPoll, wrapGroupedDocuments } from \"../wrappers\";\nimport { MessageRender } from \"./messageRender\";\nimport LazyLoadQueue from \"../lazyLoadQueue\";\nimport { AppChatsManager } from \"../../lib/appManagers/appChatsManager\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\nimport PollElement from \"../poll\";\nimport AudioElement from \"../audio\";\nimport { Message, MessageEntity, MessageReplyHeader } from \"../../layer\";\nimport { REPLIES_PEER_ID } from \"../../lib/mtproto/mtproto_config\";\nimport { FocusDirection } from \"../../helpers/fastSmoothScroll\";\nimport useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent } from \"../../hooks/useHeavyAnimationCheck\";\nimport { fastRaf } from \"../../helpers/schedulers\";\nimport { deferredPromise } from \"../../helpers/cancellablePromise\";\nimport RepliesElement from \"./replies\";\nimport DEBUG from \"../../config/debug\";\nimport { SliceEnd } from \"../../helpers/slicedArray\";\nimport serverTimeManager from \"../../lib/mtproto/serverTimeManager\";\nimport PeerTitle from \"../peerTitle\";\nimport { forEachReverse } from \"../../helpers/array\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\nimport { toast } from \"../toast\";\nimport { getElementByPoint } from \"../../helpers/dom/getElementByPoint\";\nimport { getMiddleware } from \"../../helpers/middleware\";\n\nconst USE_MEDIA_TAILS = false;\nconst IGNORE_ACTIONS: Message.messageService['action']['_'][] = [/* 'messageActionHistoryClear' */];\n\nconst TEST_SCROLL_TIMES: number = undefined;\nlet TEST_SCROLL = TEST_SCROLL_TIMES;\n\nlet queueId = 0;\n\nexport default class ChatBubbles {\n bubblesContainer: HTMLDivElement;\n chatInner: HTMLDivElement;\n scrollable: Scrollable;\n\n private getHistoryTopPromise: Promise<boolean>;\n private getHistoryBottomPromise: Promise<boolean>;\n\n public peerId = 0;\n //public messagesCount: number = -1;\n\n public unreadOut = new Set<number>();\n public needUpdate: {replyToPeerId: number, replyMid: number, mid: number}[] = []; // if need wrapSingleMessage\n\n public bubbles: {[mid: string]: HTMLDivElement} = {};\n public dateMessages: {[timestamp: number]: { \n div: HTMLDivElement, \n firstTimestamp: number, \n container: HTMLDivElement,\n timeout?: number \n }} = {};\n\n private scrolledDown = true;\n private isScrollingTimeout = 0;\n\n private stickyIntersector: StickyIntersector;\n\n private unreadedObserver: IntersectionObserver;\n private unreaded: number[] = [];\n\n public bubbleGroups: BubbleGroups;\n\n private preloader: ProgressivePreloader = null;\n \n private loadedTopTimes = 0;\n private loadedBottomTimes = 0;\n\n public messagesQueuePromise: Promise<void> = null;\n private messagesQueue: {message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise<void>[]}[] = [];\n private messagesQueueOnRender: () => void = null;\n private messagesQueueOnRenderAdditional: () => void = null;\n\n private firstUnreadBubble: HTMLDivElement = null;\n private attachedUnreadBubble: boolean;\n\n public lazyLoadQueue: LazyLoadQueue;\n\n private middleware = getMiddleware();\n\n private log: ReturnType<typeof logger>;\n\n public listenerSetter: ListenerSetter;\n\n public replyFollowHistory: number[] = [];\n\n public isHeavyAnimationInProgress = false;\n public scrollingToNewBubble: HTMLElement;\n\n public isFirstLoad = true;\n private needReflowScroll: boolean;\n\n constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appStickersManager: AppStickersManager, private appUsersManager: AppUsersManager, private appInlineBotsManager: AppInlineBotsManager, private appPhotosManager: AppPhotosManager, private appDocsManager: AppDocsManager, private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager, private storage: typeof sessionStorage) {\n //this.chat.log.error('Bubbles construction');\n \n this.listenerSetter = new ListenerSetter();\n\n this.bubblesContainer = document.createElement('div');\n this.bubblesContainer.classList.add('bubbles', 'scrolled-down');\n\n this.chatInner = document.createElement('div');\n this.chatInner.classList.add('bubbles-inner');\n\n this.setScroll();\n\n this.bubblesContainer.append(this.scrollable.container);\n\n // * constructor end\n\n this.log = this.chat.log;\n this.bubbleGroups = new BubbleGroups(this.chat);\n this.preloader = new ProgressivePreloader({\n cancelable: false\n });\n this.lazyLoadQueue = new LazyLoadQueue();\n this.lazyLoadQueue.queueId = ++queueId;\n\n // * events\n\n // will call when sent for update pos\n this.listenerSetter.add(rootScope, 'history_update', (e) => {\n const {storage, peerId, mid} = e;\n \n if(mid && peerId === this.peerId && this.chat.getMessagesStorage() === storage) {\n const bubble = this.bubbles[mid];\n if(!bubble) return;\n\n const message = this.chat.getMessage(mid);\n \n if(+bubble.dataset.timestamp >= (message.date + serverTimeManager.serverTimeOffset - 1)) {\n //this.bubbleGroups.addBubble(bubble, message, false); // ! TEMP COMMENTED\n return;\n }\n\n this.setBubblePosition(bubble, message, false);\n //this.log('history_update', this.bubbles[mid], mid, message);\n\n if(this.scrollingToNewBubble) {\n this.scrollToNewLastBubble();\n }\n\n //this.renderMessage(message, false, false, bubble);\n }\n });\n\n //this.listenerSetter.add(rootScope, '')\n\n this.listenerSetter.add(rootScope, 'dialog_flush', (e) => {\n let peerId: number = e.peerId;\n if(this.peerId === peerId) {\n this.deleteMessagesByIds(Object.keys(this.bubbles).map(m => +m));\n }\n });\n\n // Calls when message successfully sent and we have an id\n this.listenerSetter.add(rootScope, 'message_sent', (e) => {\n const {storage, tempId, tempMessage, mid} = e;\n\n // ! can't use peerId to validate here, because id can be the same in 'scheduled' and 'chat' types\n if(this.chat.getMessagesStorage() !== storage) {\n return;\n }\n \n //this.log('message_sent', e);\n\n const mounted = this.getMountedBubble(tempId, tempMessage) || this.getMountedBubble(mid);\n if(mounted) {\n const message = this.chat.getMessage(mid);\n const bubble = mounted.bubble;\n //this.bubbles[mid] = bubble;\n \n /////this.log('message_sent', bubble);\n\n if(message.replies) {\n const repliesElement = bubble.querySelector('replies-element') as RepliesElement;\n if(repliesElement) {\n repliesElement.message = message;\n repliesElement.init();\n }\n }\n\n if(message.media?.document && !message.media.document.type) {\n const div = bubble.querySelector(`.document-container[data-mid=\"${tempId}\"] .document`);\n if(div) {\n div.replaceWith(wrapDocument({message}));\n }\n }\n\n // set new mids to album items for mediaViewer\n if(message.grouped_id) {\n const item = (bubble.querySelector(`.grouped-item[data-mid=\"${tempId}\"]`) as HTMLElement) || bubble; // * it can be .document-container\n if(item) {\n item.dataset.mid = '' + mid;\n }\n }\n\n if(message.media?.poll) {\n const pollElement = bubble.querySelector('poll-element') as PollElement;\n if(pollElement) {\n const newPoll = message.media.poll;\n pollElement.message = message;\n pollElement.setAttribute('poll-id', newPoll.id);\n pollElement.setAttribute('message-id', '' + mid);\n }\n }\n\n if(message.media?.document) {\n const element = bubble.querySelector(`audio-element[message-id=\"${tempId}\"], .document[data-doc-id=\"${tempId}\"]`) as HTMLElement;\n if(element) {\n if(element instanceof AudioElement) {\n element.setAttribute('doc-id', message.media.document.id);\n element.setAttribute('message-id', '' + mid);\n element.message = message;\n element.onLoad(true);\n } else {\n element.dataset.docId = message.media.document.id;\n }\n }\n }\n\n /* bubble.classList.remove('is-sending');\n bubble.classList.add('is-sent');\n bubble.dataset.mid = '' + mid;\n\n this.bubbleGroups.removeBubble(bubble, tempId); */\n\n if(message.media?.webpage && !bubble.querySelector('.web')) {\n getHeavyAnimationPromise().then(() => {\n this.renderMessage(message, true, false, bubble, false);\n });\n /* const mounted = this.getMountedBubble(mid);\n if(!mounted) return;\n this.renderMessage(mounted.message, true, false, mounted.bubble, false); */\n }\n \n //delete this.bubbles[tempId];\n } else {\n this.log.warn('message_sent there is no bubble', e);\n }\n\n if(this.bubbles[tempId]) {\n const bubble = this.bubbles[tempId];\n this.bubbles[mid] = bubble;\n delete this.bubbles[tempId];\n\n //getHeavyAnimationPromise().then(() => {\n fastRaf(() => {\n bubble.classList.remove('is-sending');\n bubble.classList.add(this.peerId === rootScope.myId && this.chat.type !== 'scheduled' ? 'is-read' : 'is-sent');\n });\n //});\n\n bubble.dataset.mid = '' + mid;\n }\n\n if(this.unreadOut.has(tempId)) {\n this.unreadOut.delete(tempId);\n this.unreadOut.add(mid);\n }\n\n // * check timing of scheduled message\n if(this.chat.type === 'scheduled') {\n const timestamp = Date.now() / 1000 | 0;\n const maxTimestamp = tempMessage.date - 10;\n //this.log('scheduled timing:', timestamp, maxTimestamp);\n if(timestamp >= maxTimestamp) {\n this.deleteMessagesByIds([mid]);\n }\n }\n });\n\n this.listenerSetter.add(rootScope, 'message_edit', (e) => {\n fastRaf(() => {\n const {storage, peerId, mid} = e;\n \n if(peerId !== this.peerId || storage !== this.chat.getMessagesStorage()) return;\n const mounted = this.getMountedBubble(mid);\n if(!mounted) return;\n\n const updatePosition = this.chat.type === 'scheduled';\n this.renderMessage(mounted.message, true, false, mounted.bubble, updatePosition);\n\n if(updatePosition) {\n (this.messagesQueuePromise || Promise.resolve()).then(() => {\n this.deleteEmptyDateGroups();\n });\n }\n });\n });\n\n this.listenerSetter.add(rootScope, 'album_edit', (e) => {\n //fastRaf(() => { // ! can't use delayed smth here, need original bubble to be edited\n const {peerId, groupId, deletedMids} = e;\n \n if(peerId !== this.peerId) return;\n const mids = this.appMessagesManager.getMidsByAlbum(groupId);\n const renderedId = mids.concat(deletedMids).find(mid => this.bubbles[mid]);\n if(!renderedId) return;\n\n const renderMaxId = getObjectKeysAndSort(this.appMessagesManager.groupedMessagesStorage[groupId], 'asc').pop();\n\n this.renderMessage(this.chat.getMessage(renderMaxId), true, false, this.bubbles[renderedId], false);\n //});\n });\n\n this.listenerSetter.add(rootScope, 'messages_downloaded', (e) => {\n const {peerId, mids} = e;\n\n const middleware = this.getMiddleware();\n getHeavyAnimationPromise().then(() => {\n if(!middleware()) return;\n\n (mids as number[]).forEach(mid => {\n /* const promise = (this.scrollable.scrollLocked && this.scrollable.scrollLockedPromise) || Promise.resolve();\n promise.then(() => {\n \n }); */\n forEachReverse(this.needUpdate, (obj, idx) => {\n if(obj.replyMid === mid && obj.replyToPeerId === peerId) {\n const {mid, replyMid} = this.needUpdate.splice(idx, 1)[0];\n \n //this.log('messages_downloaded', mid, replyMid, i, this.needUpdate, this.needUpdate.length, mids, this.bubbles[mid]);\n const bubble = this.bubbles[mid];\n if(!bubble) return;\n \n const message = this.chat.getMessage(mid);\n \n const repliedMessage = this.appMessagesManager.getMessageByPeer(obj.replyToPeerId, replyMid);\n if(repliedMessage.deleted) { // ! чтобы не пыталось бесконечно загрузить удалённое сообщение\n delete message.reply_to_mid; // ! WARNING!\n }\n \n MessageRender.setReply({\n chat: this.chat,\n bubble,\n message\n });\n }\n });\n });\n });\n });\n\n this.listenerSetter.add(this.bubblesContainer, 'click', this.onBubblesClick/* , {capture: true, passive: false} */);\n\n if(DEBUG) {\n this.listenerSetter.add(this.bubblesContainer, 'dblclick', (e) => {\n const bubble = findUpClassName(e.target, 'grouped-item') || findUpClassName(e.target, 'bubble');\n if(bubble) {\n const mid = +bubble.dataset.mid\n this.log('debug message:', this.chat.getMessage(mid));\n this.highlightBubble(bubble);\n }\n });\n }\n\n this.listenerSetter.add(this.bubblesContainer, 'dblclick', (e) => {\n const bubble = (e.target as HTMLElement).classList.contains('bubble') ? e.target as HTMLElement : null;\n if(bubble) {\n const mid = +bubble.dataset.mid\n this.chat.input.initMessageReply(mid);\n }\n });\n\n /* if(false) */this.stickyIntersector = new StickyIntersector(this.scrollable.container, (stuck, target) => {\n for(const timestamp in this.dateMessages) {\n const dateMessage = this.dateMessages[timestamp];\n if(dateMessage.container === target) {\n dateMessage.div.classList.toggle('is-sticky', stuck);\n break;\n }\n }\n });\n\n\n let middleware: ReturnType<ChatBubbles['getMiddleware']>;\n useHeavyAnimationCheck(() => {\n this.isHeavyAnimationInProgress = true;\n this.lazyLoadQueue.lock();\n middleware = this.getMiddleware();\n }, () => {\n this.isHeavyAnimationInProgress = false;\n\n if(middleware && middleware()) {\n this.lazyLoadQueue.unlock();\n this.lazyLoadQueue.refresh();\n }\n\n middleware = null;\n }, this.listenerSetter);\n }\n\n public constructPeerHelpers() {\n // will call when message is sent (only 1)\n this.listenerSetter.add(rootScope, 'history_append', (e) => {\n const {peerId, storage, mid} = e;\n\n if(peerId !== this.peerId || storage !== this.chat.getMessagesStorage()) return;\n\n if(!this.scrollable.loadedAll.bottom) {\n this.chat.setMessageId();\n } else {\n this.renderNewMessagesByIds([mid], true);\n }\n });\n\n this.listenerSetter.add(rootScope, 'history_multiappend', (e) => {\n const msgIdsByPeer = e;\n\n if(!(this.peerId in msgIdsByPeer)) return;\n const msgIds = Array.from(msgIdsByPeer[this.peerId] as number[]).slice().sort((a, b) => b - a);\n this.renderNewMessagesByIds(msgIds);\n });\n \n this.listenerSetter.add(rootScope, 'history_delete', (e) => {\n const {peerId, msgs} = e;\n\n const mids = Object.keys(msgs).map(s => +s);\n\n if(peerId === this.peerId) {\n this.deleteMessagesByIds(mids);\n }\n });\n\n this.listenerSetter.add(rootScope, 'dialog_unread', (e) => {\n const info = e;\n\n if(info.peerId === this.peerId) {\n this.chat.input.setUnreadCount();\n this.updateUnreadByDialog();\n }\n });\n\n this.listenerSetter.add(rootScope, 'dialogs_multiupdate', (e) => {\n const dialogs = e;\n\n if(dialogs[this.peerId]) {\n this.chat.input.setUnreadCount();\n }\n });\n\n this.listenerSetter.add(rootScope, 'dialog_notify_settings', (dialog) => {\n if(this.peerId === dialog.peerId) {\n this.chat.input.setUnreadCount();\n }\n });\n\n this.unreadedObserver = new IntersectionObserver((entries) => {\n if(this.chat.appImManager.offline) { // ! but you can scroll the page without triggering 'focus', need something now\n return;\n }\n\n const readed: number[] = [];\n \n entries.forEach(entry => {\n if(entry.isIntersecting) {\n const target = entry.target as HTMLElement;\n const mid = +target.dataset.mid;\n readed.push(mid);\n this.unreadedObserver.unobserve(target);\n }\n });\n\n if(readed.length) {\n let maxId = Math.max(...readed);\n\n if(this.scrollable.loadedAll.bottom) {\n const bubblesMaxId = Math.max(...Object.keys(this.bubbles).map(i => +i));\n if(maxId >= bubblesMaxId) {\n maxId = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId).maxId || maxId;\n }\n }\n\n let length = readed.length;\n for(let i = this.unreaded.length - 1; i >= 0; --i) {\n if(this.unreaded[i] <= maxId) {\n length++;\n this.unreaded.splice(i, 1);\n }\n }\n\n if(DEBUG) {\n this.log('will readHistory by ids:', maxId, length);\n }\n \n /* false && */ this.appMessagesManager.readHistory(this.peerId, maxId, this.chat.threadId).catch((err: any) => {\n this.log.error('readHistory err:', err);\n this.appMessagesManager.readHistory(this.peerId, maxId, this.chat.threadId);\n });\n }\n });\n\n if('ResizeObserver' in window) {\n let wasHeight = this.scrollable.container.offsetHeight;\n let resizing = false;\n let skip = false;\n let scrolled = 0;\n let part = 0;\n let rAF = 0;\n\n const onResizeEnd = () => {\n const height = this.scrollable.container.offsetHeight;\n const isScrolledDown = this.scrollable.isScrolledDown;\n if(height !== wasHeight && (!skip || !isScrolledDown)) { // * fix opening keyboard while ESG is active, offsetHeight will change right between 'start' and this first frame\n part += wasHeight - height;\n }\n\n /* if(DEBUG) {\n this.log('resize end', scrolled, part, this.scrollable.scrollTop, height, wasHeight, this.scrollable.isScrolledDown);\n } */\n\n if(part) {\n this.scrollable.scrollTop += Math.round(part);\n }\n\n wasHeight = height;\n scrolled = 0;\n rAF = 0;\n part = 0;\n resizing = false;\n skip = false;\n };\n\n const setEndRAF = (single: boolean) => {\n if(rAF) window.cancelAnimationFrame(rAF);\n rAF = window.requestAnimationFrame(single ? onResizeEnd : () => {\n rAF = window.requestAnimationFrame(onResizeEnd);\n //this.log('resize after RAF', part);\n });\n };\n\n const processEntries = (entries: any) => {\n if(skip) {\n setEndRAF(false);\n return;\n }\n\n const entry = entries[0];\n const height = entry.contentRect.height;/* Math.ceil(entry.contentRect.height); */\n \n if(!wasHeight) {\n wasHeight = height;\n return;\n }\n\n const realDiff = wasHeight - height;\n let diff = realDiff + part;\n const _part = diff % 1;\n diff -= _part;\n \n if(!resizing) {\n resizing = true;\n\n /* if(DEBUG) {\n this.log('resize start', realDiff, this.scrollable.scrollTop, this.scrollable.container.offsetHeight, this.scrollable.isScrolledDown);\n } */\n\n if(realDiff < 0 && this.scrollable.isScrolledDown) {\n //if(isSafari) { // * fix opening keyboard while ESG is active \n part = -realDiff;\n //}\n\n skip = true;\n setEndRAF(false);\n return;\n }\n }\n\n scrolled += diff;\n\n /* if(DEBUG) {\n this.log('resize', wasHeight - height, diff, this.scrollable.container.offsetHeight, this.scrollable.isScrolledDown, height, wasHeight);\n } */\n\n if(diff) {\n const needScrollTop = this.scrollable.scrollTop + diff;\n this.scrollable.scrollTop = needScrollTop;\n }\n \n setEndRAF(false);\n\n part = _part;\n wasHeight = height;\n };\n\n // @ts-ignore\n const resizeObserver = new ResizeObserver(processEntries);\n resizeObserver.observe(this.bubblesContainer);\n }\n }\n\n public constructPinnedHelpers() {\n this.listenerSetter.add(rootScope, 'peer_pinned_messages', (e) => {\n const {peerId, mids, pinned} = e;\n if(peerId !== this.peerId) return;\n\n if(mids) {\n if(!pinned) {\n this.deleteMessagesByIds(mids);\n }\n }\n });\n }\n\n public constructScheduledHelpers() {\n const onUpdate = () => {\n this.chat.topbar.setTitle(Object.keys(this.appMessagesManager.getScheduledMessagesStorage(this.peerId)).length);\n };\n\n this.listenerSetter.add(rootScope, 'scheduled_new', (e) => {\n const {peerId, mid} = e;\n if(peerId !== this.peerId) return;\n\n this.renderNewMessagesByIds([mid]);\n onUpdate();\n });\n\n this.listenerSetter.add(rootScope, 'scheduled_delete', (e) => {\n const {peerId, mids} = e;\n if(peerId !== this.peerId) return;\n\n this.deleteMessagesByIds(mids);\n onUpdate();\n });\n }\n\n public onBubblesClick = (e: Event) => {\n let target = e.target as HTMLElement;\n let bubble: HTMLElement = null;\n try {\n bubble = findUpClassName(target, 'bubble');\n } catch(err) {}\n \n if(!bubble) return;\n\n if(bubble.classList.contains('is-date') && findUpClassName(target, 'bubble-content')) {\n if(bubble.classList.contains('is-sticky') && !this.chatInner.classList.contains('is-scrolling')) {\n return;\n }\n\n for(const timestamp in this.dateMessages) {\n const d = this.dateMessages[timestamp];\n if(d.div === bubble) {\n new PopupDatePicker(new Date(+timestamp), this.onDatePick).show();\n break;\n }\n }\n\n return;\n }\n\n // ! Trusted - due to audio autoclick\n if(this.chat.selection.isSelecting && e.isTrusted) {\n if(bubble.classList.contains('service') && bubble.dataset.mid === undefined) {\n return;\n }\n\n cancelEvent(e);\n //console.log('bubble click', e);\n\n if(isTouchSupported && this.chat.selection.selectedText) {\n this.chat.selection.selectedText = undefined;\n return;\n }\n\n //this.chatSelection.toggleByBubble(bubble);\n this.chat.selection.toggleByBubble(findUpClassName(target, 'grouped-item') || bubble);\n return;\n }\n\n const contactDiv: HTMLElement = findUpClassName(target, 'contact');\n if(contactDiv) {\n this.chat.appImManager.setInnerPeer(+contactDiv.dataset.peerId);\n return;\n }\n\n const commentsDiv: HTMLElement = findUpClassName(target, 'replies');\n if(commentsDiv) {\n const bubbleMid = +bubble.dataset.mid;\n if(this.peerId === REPLIES_PEER_ID) {\n const message = this.chat.getMessage(bubbleMid) as Message.message;\n const peerId = this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id);\n const threadId = message.reply_to.reply_to_top_id;\n\n this.appMessagesManager.wrapSingleMessage(peerId, threadId).then(() => {\n this.appMessagesManager.generateThreadServiceStartMessage(this.appMessagesManager.getMessageByPeer(peerId, threadId));\n this.chat.appImManager.setInnerPeer(peerId, message.fwd_from.saved_from_msg_id, 'discussion', threadId);\n });\n } else {\n const message = this.appMessagesManager.filterMessages(this.chat.getMessage(bubbleMid), message => !!(message as Message.message).replies)[0] as Message.message;\n const replies = message.replies;\n if(replies) {\n this.appMessagesManager.getDiscussionMessage(this.peerId, message.mid).then(message => {\n this.chat.appImManager.setInnerPeer(-replies.channel_id, undefined, 'discussion', (message as MyMessage).mid);\n });\n }\n }\n\n return;\n }\n\n const nameDiv = findUpClassName(target, 'peer-title') || findUpClassName(target, 'name') || findUpTag(target, 'AVATAR-ELEMENT');\n if(nameDiv) {\n target = nameDiv || target;\n const peerId = +(target.dataset.peerId || target.getAttribute('peer'));\n const savedFrom = target.dataset.savedFrom;\n if(savedFrom) {\n const splitted = savedFrom.split('_');\n const peerId = +splitted[0];\n const msgId = +splitted[1];\n\n this.chat.appImManager.setInnerPeer(peerId, msgId);\n } else {\n if(peerId) {\n this.chat.appImManager.setInnerPeer(peerId);\n } else {\n toast(I18n.format('HidAccount', true));\n }\n }\n\n return;\n }\n\n //this.log('chatInner click:', target);\n const isVideoComponentElement = target.tagName === 'SPAN';\n /* if(isVideoComponentElement) {\n const video = target.parentElement.querySelector('video') as HTMLElement;\n if(video) {\n video.click(); // hot-fix for time and play button\n return;\n }\n } */\n\n if(bubble.classList.contains('sticker') && target.parentElement.classList.contains('attachment')) {\n const messageId = +bubble.dataset.mid;\n const message = this.chat.getMessage(messageId);\n\n const doc = message.media?.document;\n\n if(doc?.stickerSetInput) {\n new PopupStickers(doc.stickerSetInput).show();\n }\n\n return;\n }\n\n if((target.tagName === 'IMG' && !target.classList.contains('emoji') && !target.classList.contains('document-thumb')) \n || target.classList.contains('album-item')\n || isVideoComponentElement\n || (target.tagName === 'VIDEO' && !bubble.classList.contains('round'))) {\n let messageId = +findUpClassName(target, 'album-item')?.dataset.mid || +bubble.dataset.mid;\n let message = this.chat.getMessage(messageId);\n if(!message) {\n this.log.warn('no message by messageId:', messageId);\n return;\n }\n\n let targets: {element: HTMLElement, mid: number, peerId: number}[] = [];\n let ids = Object.keys(this.bubbles).map(k => +k).filter(id => {\n //if(!this.scrollable.visibleElements.find(e => e.element === this.bubbles[id])) return false;\n\n let message = this.chat.getMessage(id);\n \n return message.media && (message.media.photo || (message.media.document && (message.media.document.type === 'video' || message.media.document.type === 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)));\n }).sort((a, b) => a - b);\n\n ids.forEach(id => {\n let withTail = this.bubbles[id].classList.contains('with-media-tail');\n let str = '.album-item video, .album-item img, .preview video, .preview img, ';\n if(withTail) {\n str += '.bubble__media-container';\n } else {\n str += '.attachment video, .attachment img';\n }\n\n let elements = this.bubbles[id].querySelectorAll(str) as NodeListOf<HTMLElement>;\n const parents: Set<HTMLElement> = new Set();\n Array.from(elements).forEach((element: HTMLElement) => {\n let albumItem = findUpClassName(element, 'album-item');\n const parent = albumItem || element.parentElement;\n if(parents.has(parent)) return;\n parents.add(parent);\n targets.push({\n element,\n mid: +albumItem?.dataset.mid || id,\n peerId: this.peerId\n });\n });\n });\n\n targets.sort((a, b) => a.mid - b.mid);\n\n let idx = targets.findIndex(t => t.mid === messageId);\n\n if(DEBUG) {\n this.log('open mediaViewer single with ids:', ids, idx, targets);\n }\n\n if(!targets[idx]) {\n this.log('no target for media viewer!', target);\n return;\n }\n\n new AppMediaViewer()\n .setSearchContext({\n threadId: this.chat.threadId,\n peerId: this.peerId,\n inputFilter: 'inputMessagesFilterPhotoVideo'\n })\n .openMedia(message, targets[idx].element, 0, true, targets.slice(0, idx), targets.slice(idx + 1));\n \n cancelEvent(e);\n //appMediaViewer.openMedia(message, target as HTMLImageElement);\n return;\n }\n \n if(['IMG', 'DIV', 'SPAN'/* , 'A' */].indexOf(target.tagName) === -1) target = findUpTag(target, 'DIV');\n \n if(['DIV', 'SPAN'].indexOf(target.tagName) !== -1/* || target.tagName === 'A' */) {\n if(target.classList.contains('goto-original')) {\n const savedFrom = bubble.dataset.savedFrom;\n const splitted = savedFrom.split('_');\n const peerId = +splitted[0];\n const msgId = +splitted[1];\n ////this.log('savedFrom', peerId, msgID);\n this.chat.appImManager.setInnerPeer(peerId, msgId);\n return;\n } else if(target.classList.contains('forward')) {\n const mid = +bubble.dataset.mid;\n new PopupForward(this.peerId, [mid]);\n //appSidebarRight.forwardTab.open([mid]);\n return;\n }\n \n let isReplyClick = false;\n \n try {\n isReplyClick = !!findUpClassName(e.target, 'reply');\n } catch(err) {}\n \n if(isReplyClick && bubble.classList.contains('is-reply')/* || bubble.classList.contains('forwarded') */) {\n const bubbleMid = +bubble.dataset.mid;\n this.replyFollowHistory.push(bubbleMid);\n\n const message = this.chat.getMessage(bubbleMid) as Message.message;\n\n const replyToPeerId = message.reply_to.reply_to_peer_id ? this.appPeersManager.getPeerId(message.reply_to.reply_to_peer_id) : this.peerId;\n const replyToMid = message.reply_to.reply_to_msg_id;\n\n this.chat.appImManager.setInnerPeer(replyToPeerId, replyToMid, this.chat.type, this.chat.threadId);\n\n /* if(this.chat.type === 'discussion') {\n this.chat.appImManager.setMessageId(, originalMessageId);\n } else {\n this.chat.appImManager.setInnerPeer(this.peerId, originalMessageId);\n } */\n //this.chat.setMessageId(, originalMessageId);\n }\n }\n \n //console.log('chatInner click', e);\n };\n\n public onGoDownClick() {\n if(this.replyFollowHistory.length) {\n forEachReverse(this.replyFollowHistory, (mid, idx) => {\n const bubble = this.bubbles[mid];\n let bad = true;\n if(bubble) {\n const rect = bubble.getBoundingClientRect();\n bad = (this.appPhotosManager.windowH / 2) > rect.top;\n } else {\n const message = this.chat.getMessage(mid);\n if(!message.deleted) {\n bad = false;\n }\n }\n \n if(bad) {\n this.replyFollowHistory.splice(idx, 1);\n }\n });\n\n this.replyFollowHistory.sort((a, b) => b - a);\n\n const mid = this.replyFollowHistory.pop();\n this.chat.setMessageId(mid);\n } else {\n this.chat.setMessageId(/* , dialog.top_message */);\n // const dialog = this.appMessagesManager.getDialogByPeerId(this.peerId)[0];\n \n // if(dialog) {\n // this.chat.setPeer(this.peerId/* , dialog.top_message */);\n // } else {\n // this.log('will scroll down 3');\n // this.scroll.scrollTop = this.scroll.scrollHeight;\n // }\n }\n }\n\n public getBubbleByPoint(verticalSide: 'top' | 'bottom') {\n let element = getElementByPoint(this.scrollable.container, verticalSide, 'center');\n /* if(element) {\n if(element.classList.contains('bubbles-date-group')) {\n const children = Array.from(element.children) as HTMLElement[];\n if(verticalSide === 'top') {\n element = children[this.stickyIntersector ? 2 : 1];\n } else {\n element = children[children.length - 1];\n }\n } else {\n element = findUpClassName(element, 'bubble');\n if(element && element.classList.contains('is-date')) {\n element = element.nextElementSibling as HTMLElement;\n }\n }\n } */\n if(element) element = findUpClassName(element, 'bubble');\n\n return element;\n }\n\n public getGroupedBubble(groupId: string) {\n const group = this.appMessagesManager.groupedMessagesStorage[groupId];\n for(const mid in group) {\n if(this.bubbles[mid]) {\n const maxId = Math.max(...Object.keys(group).map(id => +id)); // * because in scheduled album can be rendered by lowest mid during sending\n return {\n bubble: this.bubbles[mid], \n mid: +mid,\n message: this.chat.getMessage(maxId)\n };\n }\n }\n\n return null;\n }\n\n public getBubbleGroupedItems(bubble: HTMLElement) {\n return Array.from(bubble.querySelectorAll('.grouped-item')) as HTMLElement[];\n }\n\n public getMountedBubble(mid: number, message = this.chat.getMessage(mid)) {\n if(message.grouped_id && this.appMessagesManager.getMidsByAlbum(message.grouped_id).length > 1) {\n const a = this.getGroupedBubble(message.grouped_id);\n if(a) {\n a.bubble = a.bubble.querySelector(`.document-container[data-mid=\"${mid}\"]`) || a.bubble;\n return a;\n }\n }\n\n const bubble = this.bubbles[mid];\n if(!bubble) return;\n\n return {bubble, mid, message};\n }\n\n private findNextMountedBubbleByMsgId(mid: number) {\n return this.bubbles[getObjectKeysAndSort(this.bubbles).find(id => {\n if(id < mid) return false;\n return !!this.bubbles[id]?.parentElement;\n })];\n }\n\n public loadMoreHistory(top: boolean, justLoad = false) {\n //this.log('loadMoreHistory', top);\n if(!this.peerId || \n /* TEST_SCROLL || */ \n this.chat.setPeerPromise || \n this.isHeavyAnimationInProgress || \n (top && (this.getHistoryTopPromise || this.scrollable.loadedAll.top)) || \n (!top && (this.getHistoryBottomPromise || this.scrollable.loadedAll.bottom))\n ) {\n return;\n }\n\n // warning, если иды только отрицательные то вниз не попадёт (хотя мб и так не попадёт)\n const history = Object.keys(this.bubbles).map(id => +id).sort((a, b) => a - b);\n if(!history.length) return;\n \n if(top) {\n if(DEBUG) {\n this.log('Will load more (up) history by id:', history[0], 'maxId:', history[history.length - 1], justLoad/* , history */);\n }\n\n /* if(history.length === 75) {\n this.log('load more', this.scrollable.scrollHeight, this.scrollable.scrollTop, this.scrollable);\n return;\n } */\n /* false && */this.getHistory(history[0], true, undefined, undefined, justLoad);\n } else {\n //let dialog = this.appMessagesManager.getDialogByPeerId(this.peerId)[0];\n const historyStorage = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId);\n \n // if scroll down after search\n if(history.indexOf(historyStorage.maxId) !== -1) {\n this.scrollable.loadedAll.bottom = true;\n return;\n }\n\n if(DEBUG) {\n this.log('Will load more (down) history by id:', history[history.length - 1], justLoad/* , history */);\n }\n\n /* false && */this.getHistory(history[history.length - 1], false, true, undefined, justLoad);\n }\n }\n\n public onScroll = () => {\n //return;\n \n // * В таком случае, кнопка не будет моргать если чат в самом низу, и правильно отработает случай написания нового сообщения и проскролла вниз\n if(this.isHeavyAnimationInProgress && this.scrolledDown) return;\n //lottieLoader.checkAnimations(false, 'chat');\n\n if(!isTouchSupported) {\n if(this.isScrollingTimeout) {\n clearTimeout(this.isScrollingTimeout);\n } else if(!this.chatInner.classList.contains('is-scrolling')) {\n this.chatInner.classList.add('is-scrolling');\n }\n \n this.isScrollingTimeout = window.setTimeout(() => {\n this.chatInner.classList.remove('is-scrolling');\n this.isScrollingTimeout = 0;\n }, 1350);\n }\n \n if(this.scrollable.getDistanceToEnd() < 300 && this.scrollable.loadedAll.bottom) {\n this.bubblesContainer.classList.add('scrolled-down');\n this.scrolledDown = true;\n } else if(this.bubblesContainer.classList.contains('scrolled-down')) {\n this.bubblesContainer.classList.remove('scrolled-down');\n this.scrolledDown = false;\n }\n\n if(this.chat.topbar.pinnedMessage) {\n this.chat.topbar.pinnedMessage.setCorrectIndex(this.scrollable.lastScrollDirection);\n }\n };\n\n public setScroll() {\n this.scrollable = new Scrollable(null, 'IM', /* 10300 */300);\n this.scrollable.loadedAll.top = false;\n this.scrollable.loadedAll.bottom = false;\n\n this.scrollable.container.append(this.chatInner);\n\n /* const getScrollOffset = () => {\n //return Math.round(Math.max(300, appPhotosManager.windowH / 1.5));\n return 300; \n };\n\n window.addEventListener('resize', () => {\n this.scrollable.onScrollOffset = getScrollOffset();\n });\n\n this.scrollable = new Scrollable(this.bubblesContainer, 'y', 'IM', this.chatInner, getScrollOffset()); */\n\n this.scrollable.onAdditionalScroll = this.onScroll;\n this.scrollable.onScrolledTop = () => this.loadMoreHistory(true);\n this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);\n //this.scrollable.attachSentinels(undefined, 300);\n\n if(isTouchSupported) {\n this.scrollable.container.addEventListener('touchmove', () => {\n if(this.isScrollingTimeout) {\n clearTimeout(this.isScrollingTimeout);\n } else if(!this.chatInner.classList.contains('is-scrolling')) {\n this.chatInner.classList.add('is-scrolling');\n }\n }, {passive: true});\n\n this.scrollable.container.addEventListener('touchend', () => {\n if(!this.chatInner.classList.contains('is-scrolling')) {\n return;\n }\n\n if(this.isScrollingTimeout) {\n clearTimeout(this.isScrollingTimeout);\n }\n\n this.isScrollingTimeout = window.setTimeout(() => {\n this.chatInner.classList.remove('is-scrolling');\n this.isScrollingTimeout = 0;\n }, 1350);\n }, {passive: true});\n }\n }\n\n public updateUnreadByDialog() {\n const historyStorage = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId);\n const maxId = this.peerId === rootScope.myId ? historyStorage.readMaxId : historyStorage.readOutboxMaxId;\n \n ///////this.log('updateUnreadByDialog', maxId, dialog, this.unreadOut);\n \n for(const msgId of this.unreadOut) {\n if(msgId > 0 && msgId <= maxId) {\n const bubble = this.bubbles[msgId];\n if(bubble) {\n bubble.classList.remove('is-sent');\n bubble.classList.add('is-read');\n }\n \n this.unreadOut.delete(msgId);\n }\n }\n }\n \n public deleteMessagesByIds(mids: number[], permanent = true) {\n mids.forEach(mid => {\n if(!(mid in this.bubbles)) return;\n \n /* const mounted = this.getMountedBubble(mid);\n if(!mounted) return; */\n\n const bubble = this.bubbles[mid];\n delete this.bubbles[mid];\n\n if(this.firstUnreadBubble === bubble) {\n this.firstUnreadBubble = null;\n }\n\n this.bubbleGroups.removeBubble(bubble);\n if(this.unreadedObserver) {\n this.unreadedObserver.unobserve(bubble);\n }\n //this.unreaded.findAndSplice(mid => mid === id);\n bubble.remove();\n //bubble.remove();\n });\n\n if(permanent && this.chat.selection.isSelecting) {\n this.chat.selection.deleteSelectedMids(mids);\n }\n \n animationIntersector.checkAnimations(false, CHAT_ANIMATION_GROUP);\n this.deleteEmptyDateGroups();\n }\n \n public renderNewMessagesByIds(mids: number[], scrolledDown = this.scrolledDown) {\n if(!this.scrollable.loadedAll.bottom) { // seems search active or sliced\n //this.log('renderNewMessagesByIds: seems search is active, skipping render:', mids);\n return;\n }\n\n if(this.chat.threadId) {\n mids = mids.filter(mid => {\n const message = this.chat.getMessage(mid);\n const replyTo = message.reply_to as MessageReplyHeader;\n return replyTo && (replyTo.reply_to_top_id || replyTo.reply_to_msg_id) === this.chat.threadId;\n });\n }\n\n mids = mids.filter(mid => !this.bubbles[mid]);\n // ! should scroll even without new messages\n /* if(!mids.length) {\n return;\n } */\n\n const promise = this.performHistoryResult(mids, false, true);\n if(scrolledDown) {\n promise.then(() => {\n //this.log('renderNewMessagesByIDs: messagesQueuePromise after', this.scrollable.isScrolledDown);\n //this.scrollable.scrollTo(this.scrollable.scrollHeight, 'top', true, true, 5000);\n //const bubble = this.bubbles[Math.max(...mids)];\n this.scrollToNewLastBubble();\n\n //this.scrollable.scrollIntoViewNew(this.chatInner, 'end');\n\n /* setTimeout(() => {\n this.log('messagesQueuePromise afterafter:', this.chatInner.childElementCount, this.scrollable.scrollHeight);\n }, 10); */\n });\n }\n }\n\n public scrollToBubble(\n element: HTMLElement, \n position: ScrollLogicalPosition,\n forceDirection?: FocusDirection,\n forceDuration?: number\n ) {\n // * 4 = .25rem\n const bubble = findUpClassName(element, 'bubble');\n\n // * if it's a start, then scroll to start of the group\n if(position === 'center' && whichChild(bubble) === (this.stickyIntersector ? 2 : 1)) {\n const dateGroup = bubble.parentElement;\n if(whichChild(dateGroup) === 0) {\n element = dateGroup;\n position = 'start';\n }\n }\n\n return this.scrollable.scrollIntoViewNew(element, position, 4, undefined, forceDirection, forceDuration);\n }\n\n public scrollToNewLastBubble() {\n const bubble = this.chatInner.lastElementChild.lastElementChild as HTMLElement;\n\n /* if(DEBUG) {\n this.log('scrollToNewLastBubble: will scroll into view:', bubble);\n } */\n\n if(bubble) {\n this.scrollingToNewBubble = bubble;\n this.scrollToBubble(bubble, 'end').then(() => {\n this.scrollingToNewBubble = null;\n });\n }\n }\n\n public highlightBubble(element: HTMLElement) {\n const datasetKey = 'highlightTimeout';\n if(element.dataset[datasetKey]) {\n clearTimeout(+element.dataset[datasetKey]);\n element.classList.remove('is-highlighted');\n void element.offsetWidth; // reflow\n }\n\n element.classList.add('is-highlighted');\n element.dataset[datasetKey] = '' + setTimeout(() => {\n element.classList.remove('is-highlighted');\n delete element.dataset[datasetKey];\n }, 2000);\n }\n\n public getDateContainerByMessage(message: any, reverse: boolean) {\n const date = new Date(message.date * 1000);\n date.setHours(0, 0, 0);\n const dateTimestamp = date.getTime();\n if(!(dateTimestamp in this.dateMessages)) {\n let dateElement: HTMLElement;\n \n const today = new Date();\n today.setHours(0, 0, 0, 0);\n \n if(today.getTime() === date.getTime()) {\n dateElement = i18n(this.chat.type === 'scheduled' ? 'Chat.Date.ScheduledForToday' : 'Date.Today');\n } else {\n const options: Intl.DateTimeFormatOptions = {\n day: 'numeric',\n month: 'long'\n };\n\n if(date.getFullYear() !== today.getFullYear()) {\n options.year = 'numeric';\n }\n\n dateElement = new I18n.IntlDateElement({\n date,\n options\n }).element;\n\n if(this.chat.type === 'scheduled') {\n dateElement = i18n('Chat.Date.ScheduledFor', [dateElement]);\n }\n }\n\n /* if(this.chat.type === 'scheduled') {\n str = 'Scheduled for ' + str;\n } */\n \n const div = document.createElement('div');\n div.className = 'bubble service is-date';\n const bubbleContent = document.createElement('div');\n bubbleContent.classList.add('bubble-content');\n const serviceMsg = document.createElement('div');\n serviceMsg.classList.add('service-msg');\n\n serviceMsg.append(dateElement);\n\n bubbleContent.append(serviceMsg);\n div.append(bubbleContent);\n ////////this.log('need to render date message', dateTimestamp, str);\n\n const container = document.createElement('div');\n container.className = 'bubbles-date-group';\n\n const haveTimestamps = getObjectKeysAndSort(this.dateMessages, 'asc');\n let i = 0;\n for(; i < haveTimestamps.length; ++i) {\n const t = haveTimestamps[i];\n if(dateTimestamp < t) {\n break;\n }\n }\n \n this.dateMessages[dateTimestamp] = {\n div,\n container,\n firstTimestamp: date.getTime()\n };\n\n container.append(div);\n\n positionElementByIndex(container, this.chatInner, i);\n\n /* if(reverse) {\n this.chatInner.prepend(container);\n } else {\n this.chatInner.append(container);\n } */\n\n if(this.stickyIntersector) {\n this.stickyIntersector.observeStickyHeaderChanges(container);\n }\n }\n\n return this.dateMessages[dateTimestamp];\n }\n\n public destroy() {\n //this.chat.log.error('Bubbles destroying');\n\n this.scrollable.onScrolledTop = this.scrollable.onScrolledBottom = this.scrollable.onAdditionalScroll = null;\n\n this.listenerSetter.removeAll();\n\n this.lazyLoadQueue.clear();\n this.unreadedObserver && this.unreadedObserver.disconnect();\n this.stickyIntersector && this.stickyIntersector.disconnect();\n\n delete this.lazyLoadQueue;\n this.unreadedObserver && delete this.unreadedObserver;\n this.stickyIntersector && delete this.stickyIntersector;\n }\n\n public cleanup(bubblesToo = false) {\n ////console.time('appImManager cleanup');\n this.scrollable.loadedAll.top = false;\n this.scrollable.loadedAll.bottom = false;\n\n if(TEST_SCROLL !== undefined) {\n TEST_SCROLL = TEST_SCROLL_TIMES;\n }\n\n this.bubbles = {};\n this.dateMessages = {};\n this.bubbleGroups.cleanup();\n this.unreadOut.clear();\n this.needUpdate.length = 0;\n this.lazyLoadQueue.clear();\n\n // clear messages\n if(bubblesToo) {\n this.scrollable.container.textContent = '';\n }\n\n this.firstUnreadBubble = null;\n this.attachedUnreadBubble = false;\n\n this.messagesQueue.length = 0;\n this.messagesQueuePromise = null;\n\n this.getHistoryTopPromise = this.getHistoryBottomPromise = undefined;\n\n if(this.stickyIntersector) {\n this.stickyIntersector.disconnect();\n }\n \n if(this.unreadedObserver) {\n this.unreadedObserver.disconnect();\n this.unreaded.length = 0;\n }\n\n this.loadedTopTimes = this.loadedBottomTimes = 0;\n\n this.middleware.clean();\n\n ////console.timeEnd('appImManager cleanup');\n }\n\n public setPeer(peerId: number, lastMsgId?: number): {cached?: boolean, promise: Chat['setPeerPromise']} {\n //console.time('appImManager setPeer');\n //console.time('appImManager setPeer pre promise');\n ////console.time('appImManager: pre render start');\n if(!peerId) {\n this.cleanup(true);\n this.peerId = 0;\n return null;\n }\n\n const samePeer = this.peerId === peerId;\n\n /* if(samePeer && this.chat.setPeerPromise) {\n return {cached: true, promise: this.chat.setPeerPromise};\n } */\n\n const historyStorage = this.appMessagesManager.getHistoryStorage(peerId, this.chat.threadId);\n let topMessage = this.chat.type === 'pinned' ? this.appMessagesManager.pinnedMessages[peerId].maxId : historyStorage.maxId ?? 0;\n const isTarget = lastMsgId !== undefined;\n\n // * this one will fix topMessage for null message in history (e.g. channel comments with only 1 comment and it is a topMessage)\n if(this.chat.type !== 'pinned' && topMessage && !historyStorage.history.slice.includes(topMessage)) {\n topMessage = 0;\n }\n\n let readMaxId = 0, savedPosition: ReturnType<AppImManager['getChatSavedPosition']>;\n if(!isTarget) {\n if(!samePeer) {\n savedPosition = this.chat.appImManager.getChatSavedPosition(this.chat);\n }\n\n if(savedPosition) {\n \n } else if(topMessage) {\n readMaxId = this.appMessagesManager.getReadMaxIdIfUnread(peerId, this.chat.threadId);\n if(/* dialog.unread_count */readMaxId && !samePeer) {\n lastMsgId = readMaxId;\n } else {\n lastMsgId = topMessage;\n //lastMsgID = topMessage;\n }\n }\n }\n\n const isJump = lastMsgId !== topMessage;\n \n if(samePeer) {\n const mounted = this.getMountedBubble(lastMsgId);\n if(mounted) {\n if(isTarget) {\n this.scrollToBubble(mounted.bubble, 'center');\n this.highlightBubble(mounted.bubble);\n this.chat.dispatchEvent('setPeer', lastMsgId, false);\n } else if(topMessage && !isJump) {\n //this.log('will scroll down', this.scroll.scrollTop, this.scroll.scrollHeight);\n this.scrollable.scrollTop = this.scrollable.scrollHeight;\n this.chat.dispatchEvent('setPeer', lastMsgId, true);\n }\n \n return null;\n }\n } else {\n if(this.peerId) { // * set new queue id if new peer (setting not from 0)\n this.lazyLoadQueue.queueId = ++queueId;\n this.chat.apiManager.setQueueId(this.chat.bubbles.lazyLoadQueue.queueId);\n }\n\n this.peerId = peerId;\n this.replyFollowHistory.length = 0;\n }\n\n if(DEBUG) {\n this.log('setPeer peerId:', this.peerId, historyStorage, lastMsgId, topMessage);\n }\n\n // add last message, bc in getHistory will load < max_id\n const additionMsgId = isJump || this.chat.type === 'scheduled' ? 0 : topMessage;\n\n /* this.setPeerPromise = null;\n this.preloader.detach();\n return true; */\n\n //////appSidebarRight.toggleSidebar(true);\n\n let maxBubbleId = 0;\n if(samePeer) {\n let el = this.getBubbleByPoint('bottom'); // ! this may not work if being called when chat is hidden\n //this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);\n if(el) {\n maxBubbleId = +el.dataset.mid;\n }\n\n if(maxBubbleId <= 0) {\n maxBubbleId = Math.max(...Object.keys(this.bubbles).map(mid => +mid));\n }\n } else {\n this.isFirstLoad = true;\n }\n\n const oldChatInner = this.chatInner;\n this.cleanup();\n this.chatInner = document.createElement('div');\n if(samePeer) {\n this.chatInner.className = oldChatInner.className;\n this.chatInner.classList.remove('disable-hover', 'is-scrolling');\n } else {\n this.chatInner.classList.add('bubbles-inner');\n }\n\n this.lazyLoadQueue.lock();\n\n let result: ReturnType<ChatBubbles['getHistory']>;\n if(!savedPosition) {\n result = this.getHistory(lastMsgId, true, isJump, additionMsgId);\n } else {\n result = {\n promise: getHeavyAnimationPromise().then(() => {\n return this.performHistoryResult(savedPosition.mids, true, false, undefined);\n }) as any,\n cached: true\n };\n }\n\n const {promise, cached} = result;\n\n // clear \n if(!cached) {\n if(!samePeer) {\n this.scrollable.container.textContent = '';\n //oldChatInner.remove();\n this.chat.finishPeerChange(isTarget, isJump, lastMsgId);\n this.preloader.attach(this.bubblesContainer);\n }\n }\n\n //console.timeEnd('appImManager setPeer pre promise');\n \n animationIntersector.lockGroup(CHAT_ANIMATION_GROUP);\n const setPeerPromise = promise.then(() => {\n ////this.log('setPeer removing preloader');\n\n if(cached) {\n if(!samePeer) {\n this.chat.finishPeerChange(isTarget, isJump, lastMsgId); // * костыль\n }\n } else {\n this.preloader.detach();\n }\n\n replaceContent(this.scrollable.container, this.chatInner);\n\n animationIntersector.unlockGroup(CHAT_ANIMATION_GROUP);\n animationIntersector.checkAnimations(false, CHAT_ANIMATION_GROUP/* , true */);\n\n //fastRaf(() => {\n this.lazyLoadQueue.unlock();\n //});\n\n //if(dialog && lastMsgID && lastMsgID !== topMessage && (this.bubbles[lastMsgID] || this.firstUnreadBubble)) {\n if(savedPosition) {\n this.scrollable.scrollTop = savedPosition.top;\n /* const mountedByLastMsgId = this.getMountedBubble(lastMsgId);\n let bubble: HTMLElement = mountedByLastMsgId?.bubble;\n if(!bubble?.parentElement) {\n bubble = this.findNextMountedBubbleByMsgId(lastMsgId);\n }\n\n if(bubble) {\n const top = bubble.getBoundingClientRect().top;\n const distance = savedPosition.top - top;\n this.scrollable.scrollTop += distance;\n } */\n } else if((topMessage && isJump) || isTarget) {\n const fromUp = maxBubbleId > 0 && (maxBubbleId < lastMsgId || lastMsgId < 0);\n const followingUnread = readMaxId === lastMsgId && !isTarget;\n if(!fromUp && samePeer) {\n this.scrollable.scrollTop = 99999;\n } else if(fromUp/* && (samePeer || forwardingUnread) */) {\n this.scrollable.scrollTop = 0;\n }\n\n const mountedByLastMsgId = this.getMountedBubble(lastMsgId);\n let bubble: HTMLElement = (followingUnread && this.firstUnreadBubble) || mountedByLastMsgId?.bubble;\n if(!bubble?.parentElement) {\n bubble = this.findNextMountedBubbleByMsgId(lastMsgId);\n }\n \n // ! sometimes there can be no bubble\n if(bubble) {\n this.scrollToBubble(bubble, followingUnread ? 'start' : 'center', !samePeer ? FocusDirection.Static : undefined);\n if(!followingUnread) {\n this.highlightBubble(bubble);\n }\n }\n } else {\n this.scrollable.scrollTop = 99999;\n }\n\n this.onScroll();\n\n this.chat.dispatchEvent('setPeer', lastMsgId, !isJump);\n\n // warning\n if((!lastMsgId && !savedPosition) || this.bubbles[topMessage] || lastMsgId === topMessage) {\n this.scrollable.loadedAll.bottom = true;\n }\n\n if(savedPosition) {\n Promise.all([setPeerPromise, getHeavyAnimationPromise()]).then(() => {\n this.scrollable.checkForTriggers();\n });\n }\n\n this.log('scrolledAllDown:', this.scrollable.loadedAll.bottom);\n\n //if(!this.unreaded.length && dialog) { // lol\n if(this.scrollable.loadedAll.bottom && topMessage) { // lol\n this.onScrolledAllDown();\n }\n\n if(this.chat.type === 'chat') {\n const dialog = this.appMessagesManager.getDialogByPeerId(peerId)[0];\n if(dialog?.pFlags.unread_mark) {\n this.appMessagesManager.markDialogUnread(peerId, true);\n }\n }\n\n //this.chatInner.classList.remove('disable-hover', 'is-scrolling'); // warning, performance!\n\n /* if(!document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME)) {\n return new Promise<void>((resolve) => fastRaf(resolve));\n } */\n //console.timeEnd('appImManager setPeer');\n }).catch(err => {\n this.log.error('getHistory promise error:', err);\n this.preloader.detach();\n throw err;\n });\n\n return {cached, promise: setPeerPromise};\n }\n\n public onScrolledAllDown() {\n if(this.chat.type === 'chat' || this.chat.type === 'discussion') {\n const storage = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId);\n this.appMessagesManager.readHistory(this.peerId, storage.maxId, this.chat.threadId, true);\n }\n }\n\n public finishPeerChange() {\n const peerId = this.peerId;\n const isChannel = this.appPeersManager.isChannel(peerId);\n const canWrite = this.appMessagesManager.canWriteToPeer(peerId);\n \n this.chatInner.classList.toggle('has-rights', canWrite);\n this.bubblesContainer.classList.toggle('is-chat-input-hidden', !canWrite);\n\n this.chatInner.classList.toggle('is-chat', this.chat.isAnyGroup());\n this.chatInner.classList.toggle('is-channel', isChannel);\n }\n\n public renderMessagesQueue(message: any, bubble: HTMLDivElement, reverse: boolean, promises: Promise<any>[]) {\n /* let dateMessage = this.getDateContainerByMessage(message, reverse);\n if(reverse) dateMessage.container.insertBefore(bubble, dateMessage.div.nextSibling);\n else dateMessage.container.append(bubble);\n return; */\n\n /* if(DEBUG && message.mid === 4314759167) {\n this.log('renderMessagesQueue', message, bubble, reverse, promises);\n } */\n\n this.messagesQueue.push({message, bubble, reverse, promises});\n\n this.setMessagesQueuePromise(); \n }\n\n public setMessagesQueuePromise() {\n if(this.messagesQueuePromise || !this.messagesQueue.length) return;\n\n this.messagesQueuePromise = new Promise((resolve, reject) => {\n setTimeout(() => {\n const queue = this.messagesQueue.slice();\n this.messagesQueue.length = 0;\n\n const promises = queue.reduce((acc, {promises}) => acc.concat(promises), []);\n\n // * это нужно для того, чтобы если захочет подгрузить reply или какое-либо сообщение, то скролл не прервался\n // * если добавить этот промис - в таком случае нужно сделать, чтобы скроллило к последнему сообщению после рендера\n // promises.push(getHeavyAnimationPromise());\n\n this.log('promises to call', promises, queue, this.isHeavyAnimationInProgress);\n const middleware = this.getMiddleware();\n Promise.all(promises).then(() => {\n if(!middleware()) {\n return Promise.reject('setMessagesQueuePromise: peer changed!');\n }\n\n if(this.messagesQueueOnRender) {\n this.messagesQueueOnRender();\n }\n\n if(this.messagesQueueOnRenderAdditional) {\n this.messagesQueueOnRenderAdditional();\n }\n\n queue.forEach(({message, bubble, reverse}) => {\n this.setBubblePosition(bubble, message, reverse);\n });\n\n //setTimeout(() => {\n resolve();\n //}, 500);\n this.messagesQueuePromise = null;\n\n if(this.messagesQueue.length) {\n this.setMessagesQueuePromise();\n }\n\n this.setUnreadDelimiter(); // не нашёл места лучше\n }).catch(reject);\n }, 0);\n });\n\n //this.messagesQueuePromise.catch(() => {});\n }\n\n public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) {\n const dateMessage = this.getDateContainerByMessage(message, reverse);\n if(this.chat.type === 'scheduled' || this.chat.type === 'pinned'/* || true */) { // ! TEMP COMMENTED\n const offset = this.stickyIntersector ? 2 : 1;\n let children = Array.from(dateMessage.container.children).slice(offset) as HTMLElement[];\n let i = 0, foundMidOnSameTimestamp = 0;\n for(; i < children.length; ++i) {\n const t = children[i];\n const timestamp = +t.dataset.timestamp;\n if(message.date < timestamp) {\n break;\n } else if(message.date === timestamp) {\n foundMidOnSameTimestamp = +t.dataset.mid;\n }\n \n if(foundMidOnSameTimestamp && message.mid < foundMidOnSameTimestamp) {\n break;\n }\n }\n \n // * 1 for date, 1 for date sentinel\n let index = offset + i;\n /* if(bubble.parentElement) { // * if already mounted\n const currentIndex = whichChild(bubble);\n if(index > currentIndex) {\n index -= 1; // * minus for already mounted\n }\n } */\n \n positionElementByIndex(bubble, dateMessage.container, index);\n } else {\n if(reverse) {\n dateMessage.container.insertBefore(bubble, dateMessage.container.children[this.stickyIntersector ? 1 : 0].nextSibling);\n } else {\n dateMessage.container.append(bubble);\n }\n }\n\n this.bubbleGroups.addBubble(bubble, message, reverse);\n }\n\n public getMiddleware() {\n return this.middleware.get();\n }\n \n // reverse means top\n public renderMessage(message: any, reverse = false, multipleRender = false, bubble: HTMLDivElement = null, updatePosition = true) {\n /* if(DEBUG) {\n this.log.debug('message to render:', message);\n } */\n if(!bubble && this.bubbles[message.mid]) {\n return;\n }\n\n //return;\n const albumMustBeRenderedFull = this.chat.type !== 'pinned';\n if(message.deleted) return;\n else if(message.grouped_id && albumMustBeRenderedFull) { // will render only last album's message\n const storage = this.appMessagesManager.groupedMessagesStorage[message.grouped_id];\n const maxId = Math.max(...Object.keys(storage).map(i => +i));\n if(message.mid < maxId) {\n return;\n }\n }\n \n const peerId = this.peerId;\n // * can't use 'message.pFlags.out' here because this check will be used to define side of message (left-right)\n const our = message.fromId === rootScope.myId || (message.pFlags.out && this.appPeersManager.isMegagroup(this.peerId));\n \n const messageDiv = document.createElement('div');\n messageDiv.classList.add('message');\n \n //messageDiv.innerText = message.message;\n\n let bubbleContainer: HTMLDivElement;\n let contentWrapper: HTMLElement;\n \n // bubble\n if(!bubble) {\n contentWrapper = document.createElement('div');\n contentWrapper.classList.add('bubble-content-wrapper');\n \n bubbleContainer = document.createElement('div');\n bubbleContainer.classList.add('bubble-content');\n \n bubble = document.createElement('div');\n bubble.classList.add('bubble');\n contentWrapper.appendChild(bubbleContainer);\n bubble.appendChild(contentWrapper);\n\n if(!our && !message.pFlags.out) {\n //this.log('not our message', message, message.pFlags.unread);\n if(message.pFlags.unread && this.unreadedObserver) {\n this.unreadedObserver.observe(bubble); \n if(!this.unreaded.indexOf(message.mid)) {\n this.unreaded.push(message.mid);\n }\n }\n }\n } else {\n const save = ['is-highlighted', 'is-group-first', 'is-group-last'];\n const wasClassNames = bubble.className.split(' ');\n const classNames = ['bubble'].concat(save.filter(c => wasClassNames.includes(c)));\n bubble.className = classNames.join(' ');\n\n contentWrapper = bubble.lastElementChild as HTMLElement;\n bubbleContainer = contentWrapper.firstElementChild as HTMLDivElement;\n bubbleContainer.innerHTML = '';\n contentWrapper.innerHTML = '';\n contentWrapper.appendChild(bubbleContainer);\n //bubbleContainer.style.marginBottom = '';\n const transitionDelay = contentWrapper.style.transitionDelay;\n contentWrapper.style.cssText = '';\n contentWrapper.style.transitionDelay = transitionDelay;\n\n if(bubble === this.firstUnreadBubble) {\n bubble.classList.add('is-first-unread');\n }\n\n // * Нужно очистить прошлую информацию, полезно если удалить последний элемент из альбома в ПОСЛЕДНЕМ БАББЛЕ ГРУППЫ (видно по аватару)\n const originalMid = +bubble.dataset.mid;\n const sameMid = +message.mid === originalMid;\n /* if(updatePosition) {\n bubble.remove(); // * for positionElementByIndex\n } */\n\n if(!sameMid) {\n delete this.bubbles[originalMid];\n }\n\n //bubble.innerHTML = '';\n }\n\n // ! reset due to album edit or delete item\n this.bubbles[+message.mid] = bubble;\n bubble.dataset.mid = message.mid;\n bubble.dataset.timestamp = message.date;\n\n const loadPromises: Promise<any>[] = [];\n\n if(message._ === 'messageService') {\n let action = message.action;\n let _ = action._;\n if(IGNORE_ACTIONS.includes(_) || (langPack.hasOwnProperty(_) && !langPack[_])) {\n return bubble;\n }\n\n bubble.className = 'bubble service';\n\n bubbleContainer.innerHTML = '';\n const s = document.createElement('div');\n s.classList.add('service-msg');\n s.append(this.appMessagesManager.wrapMessageActionTextNew(message));\n bubbleContainer.append(s);\n\n if(updatePosition) {\n this.renderMessagesQueue(message, bubble, reverse, loadPromises);\n\n if(message.pFlags.is_single) { // * Ignore 'Discussion started'\n bubble.classList.add('is-group-last');\n }\n }\n\n return bubble;\n }\n\n let messageMedia = message.media;\n\n let messageMessage: string, totalEntities: MessageEntity[];\n if(messageMedia?.document && !['video', 'gif'].includes(messageMedia.document.type)) {\n // * just filter these cases for documents caption\n } else if(message.grouped_id && albumMustBeRenderedFull) {\n const t = this.appMessagesManager.getAlbumText(message.grouped_id);\n messageMessage = t.message;\n //totalEntities = t.entities;\n totalEntities = t.totalEntities;\n } else if(messageMedia?.document?.type !== 'sticker') {\n messageMessage = message.message;\n //totalEntities = message.entities;\n totalEntities = message.totalEntities;\n }\n \n /* let richText = RichTextProcessor.wrapRichText(messageMessage, {\n entities: totalEntities\n }); */\n let richText = RichTextProcessor.wrapRichText(messageMessage, {\n entities: totalEntities\n });\n\n let canHaveTail = true;\n \n if(totalEntities && !messageMedia) {\n let emojiEntities = totalEntities.filter((e) => e._ === 'messageEntityEmoji');\n let strLength = messageMessage.length;\n let emojiStrLength = emojiEntities.reduce((acc: number, curr: any) => acc + curr.length, 0);\n \n if(emojiStrLength === strLength && emojiEntities.length <= 3) {\n let sticker = this.appStickersManager.getAnimatedEmojiSticker(messageMessage);\n if(emojiEntities.length === 1 && !messageMedia && sticker) {\n messageMedia = {\n _: 'messageMediaDocument',\n document: sticker\n };\n } else {\n let attachmentDiv = document.createElement('div');\n attachmentDiv.classList.add('attachment');\n \n attachmentDiv.innerHTML = richText;\n \n bubble.classList.add('emoji-' + emojiEntities.length + 'x');\n \n bubbleContainer.append(attachmentDiv);\n }\n\n bubble.classList.add('is-message-empty', 'emoji-big');\n canHaveTail = false;\n } else {\n messageDiv.innerHTML = richText;\n }\n \n /* if(strLength === emojiStrLength) {\n messageDiv.classList.add('emoji-only');\n messageDiv.classList.add('message-empty');\n } */\n } else {\n messageDiv.innerHTML = richText;\n }\n \n const timeSpan = MessageRender.setTime(this.chat, message, bubble, bubbleContainer, messageDiv);\n bubbleContainer.prepend(messageDiv);\n //bubble.prepend(timeSpan, messageDiv); // that's bad\n\n if(message.reply_markup && message.reply_markup._ === 'replyInlineMarkup' && message.reply_markup.rows && message.reply_markup.rows.length) {\n const rows = message.reply_markup.rows;\n\n const containerDiv = document.createElement('div');\n containerDiv.classList.add('reply-markup');\n rows.forEach((row: any) => {\n const buttons = row.buttons;\n if(!buttons || !buttons.length) return;\n\n const rowDiv = document.createElement('div');\n rowDiv.classList.add('reply-markup-row');\n\n buttons.forEach((button: any) => {\n const text = RichTextProcessor.wrapRichText(button.text, {noLinks: true, noLinebreaks: true});\n\n let buttonEl: HTMLButtonElement | HTMLAnchorElement;\n \n switch(button._) {\n case 'keyboardButtonUrl': {\n const from = this.appUsersManager.getUser(message.fromId);\n const unsafe = !(from && from.pFlags && from.pFlags.verified);\n const url = RichTextProcessor.wrapUrl(button.url, unsafe);\n buttonEl = document.createElement('a');\n buttonEl.href = url;\n buttonEl.rel = 'noopener noreferrer';\n buttonEl.target = '_blank';\n buttonEl.classList.add('is-link', 'tgico');\n\n break;\n }\n\n default: {\n buttonEl = document.createElement('button');\n break;\n }\n }\n\n buttonEl.classList.add('reply-markup-button', 'rp');\n buttonEl.innerHTML = text;\n\n ripple(buttonEl);\n\n rowDiv.append(buttonEl);\n });\n\n containerDiv.append(rowDiv);\n });\n\n attachClickEvent(containerDiv, (e) => {\n cancelEvent(e);\n let target = e.target as HTMLElement;\n\n if(!target.classList.contains('reply-markup-button')) target = findUpClassName(target, 'reply-markup-button');\n if(!target) return;\n\n const column = whichChild(target);\n const row = rows[whichChild(target.parentElement)];\n\n if(!row.buttons || !row.buttons[column]) {\n this.log.warn('no such button', row, column, message);\n return;\n }\n\n const button = row.buttons[column];\n this.appInlineBotsManager.callbackButtonClick(this.peerId, message.mid, button);\n });\n\n canHaveTail = false;\n bubble.classList.add('with-reply-markup');\n contentWrapper.append(containerDiv);\n }\n \n const isOutgoing = message.pFlags.is_outgoing/* && this.peerId !== rootScope.myId */;\n if(our) {\n if(message.pFlags.unread || isOutgoing) this.unreadOut.add(message.mid);\n let status = '';\n if(isOutgoing) status = 'is-sending';\n else status = message.pFlags.unread ? 'is-sent' : 'is-read';\n bubble.classList.add(status);\n }\n\n let messageWithReplies: Message.message;\n let withReplies: boolean;\n if(this.peerId === REPLIES_PEER_ID) {\n messageWithReplies = message;\n withReplies = true;\n } else {\n messageWithReplies = this.appMessagesManager.filterMessages(message, message => !!(message as Message.message).replies)[0] as any;\n withReplies = messageWithReplies && messageWithReplies.replies && messageWithReplies.replies.pFlags.comments && messageWithReplies.replies.channel_id !== 777;\n }\n\n if(withReplies) {\n bubble.classList.add('with-replies');\n }\n\n const isOut = our && (!message.fwd_from || this.peerId !== rootScope.myId);\n let nameContainer: HTMLElement = bubbleContainer;\n \n // media\n if(messageMedia/* && messageMedia._ === 'messageMediaPhoto' */) {\n let attachmentDiv = document.createElement('div');\n attachmentDiv.classList.add('attachment');\n \n if(!messageMessage) {\n bubble.classList.add('is-message-empty');\n }\n \n let processingWebPage = false;\n \n switch(messageMedia._) {\n case 'messageMediaPhoto': {\n const photo = messageMedia.photo;\n ////////this.log('messageMediaPhoto', photo);\n\n if(!messageMessage) {\n canHaveTail = false;\n }\n \n bubble.classList.add('hide-name', 'photo');\n \n const storage = this.appMessagesManager.groupedMessagesStorage[message.grouped_id];\n if(message.grouped_id && Object.keys(storage).length !== 1 && albumMustBeRenderedFull) {\n bubble.classList.add('is-album', 'is-grouped');\n wrapAlbum({\n groupId: message.grouped_id, \n attachmentDiv,\n middleware: this.getMiddleware(),\n isOut: our,\n lazyLoadQueue: this.lazyLoadQueue,\n chat: this.chat,\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n \n break;\n }\n \n const withTail = !isAndroid && canHaveTail && !withReplies && USE_MEDIA_TAILS;\n if(withTail) bubble.classList.add('with-media-tail');\n wrapPhoto({\n photo, \n message,\n container: attachmentDiv,\n withTail, \n isOut, \n lazyLoadQueue: this.lazyLoadQueue,\n middleware: this.getMiddleware(),\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n\n break;\n }\n \n case 'messageMediaWebPage': {\n processingWebPage = true;\n \n let webpage = messageMedia.webpage;\n ////////this.log('messageMediaWebPage', webpage);\n if(webpage._ === 'webPageEmpty') {\n break;\n } \n \n bubble.classList.add('webpage');\n \n let box = document.createElement('div');\n box.classList.add('web');\n \n let quote = document.createElement('div');\n quote.classList.add('quote');\n\n let previewResizer: HTMLDivElement, preview: HTMLDivElement;\n if(webpage.photo || webpage.document) {\n previewResizer = document.createElement('div');\n previewResizer.classList.add('preview-resizer');\n preview = document.createElement('div');\n preview.classList.add('preview');\n previewResizer.append(preview);\n }\n \n let doc: any = null;\n if(webpage.document) {\n doc = webpage.document;\n \n if(doc.type === 'gif' || doc.type === 'video') {\n //if(doc.size <= 20e6) {\n bubble.classList.add('video');\n wrapVideo({\n doc, \n container: preview, \n message, \n boxWidth: mediaSizes.active.webpage.width,\n boxHeight: mediaSizes.active.webpage.height,\n lazyLoadQueue: this.lazyLoadQueue,\n middleware: this.getMiddleware(),\n isOut,\n group: CHAT_ANIMATION_GROUP,\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n //}\n } else {\n const docDiv = wrapDocument({\n message,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n preview.append(docDiv);\n preview.classList.add('preview-with-document');\n //messageDiv.classList.add((webpage.type || 'document') + '-message');\n //doc = null;\n }\n }\n \n if(previewResizer) {\n quote.append(previewResizer);\n }\n \n let quoteTextDiv = document.createElement('div');\n quoteTextDiv.classList.add('quote-text');\n\n if(webpage.site_name) {\n let nameEl = document.createElement('a');\n nameEl.classList.add('name');\n nameEl.setAttribute('target', '_blank');\n nameEl.href = webpage.url || '#';\n nameEl.innerHTML = RichTextProcessor.wrapEmojiText(webpage.site_name);\n quoteTextDiv.append(nameEl);\n }\n\n if(webpage.rTitle) {\n let titleDiv = document.createElement('div');\n titleDiv.classList.add('title');\n titleDiv.innerHTML = webpage.rTitle;\n quoteTextDiv.append(titleDiv);\n }\n\n if(webpage.rDescription) {\n let textDiv = document.createElement('div');\n textDiv.classList.add('text');\n textDiv.innerHTML = webpage.rDescription;\n quoteTextDiv.append(textDiv);\n }\n\n quote.append(quoteTextDiv);\n\n if(webpage.photo && !doc) {\n bubble.classList.add('photo');\n\n const size = webpage.photo.sizes[webpage.photo.sizes.length - 1];\n let isSquare = false;\n if(size.w === size.h && quoteTextDiv.childElementCount) {\n bubble.classList.add('is-square-photo');\n isSquare = true;\n } else if(size.h > size.w) {\n bubble.classList.add('is-vertical-photo');\n }\n\n wrapPhoto({\n photo: webpage.photo, \n message, \n container: preview, \n boxWidth: mediaSizes.active.webpage.width, \n boxHeight: mediaSizes.active.webpage.height, \n isOut, \n lazyLoadQueue: this.lazyLoadQueue, \n middleware: this.getMiddleware(),\n loadPromises,\n withoutPreloader: isSquare,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n }\n \n box.append(quote);\n \n //bubble.prepend(box);\n messageDiv.insertBefore(box, messageDiv.lastElementChild);\n \n //this.log('night running', bubble.scrollHeight);\n \n break;\n }\n \n case 'messageMediaDocument': {\n let doc = messageMedia.document;\n\n //this.log('messageMediaDocument', doc, bubble);\n \n if(doc.sticker/* && doc.size <= 1e6 */) {\n bubble.classList.add('sticker');\n canHaveTail = false;\n \n if(doc.animated) {\n bubble.classList.add('sticker-animated');\n }\n \n let size = bubble.classList.contains('emoji-big') ? 140 : 200;\n this.appPhotosManager.setAttachmentSize(doc, attachmentDiv, size, size);\n //let preloader = new ProgressivePreloader(attachmentDiv, false);\n bubbleContainer.style.height = attachmentDiv.style.height;\n bubbleContainer.style.width = attachmentDiv.style.width;\n //appPhotosManager.setAttachmentSize(doc, bubble);\n wrapSticker({\n doc, \n div: attachmentDiv,\n middleware: this.getMiddleware(),\n lazyLoadQueue: this.lazyLoadQueue,\n group: CHAT_ANIMATION_GROUP,\n //play: !!message.pending || !multipleRender,\n play: true,\n loop: true,\n emoji: bubble.classList.contains('emoji-big') ? messageMessage : undefined,\n withThumb: true,\n loadPromises\n });\n\n break;\n } else if(doc.type === 'video' || doc.type === 'gif' || doc.type === 'round'/* && doc.size <= 20e6 */) {\n //this.log('never get free 2', doc);\n\n if(doc.type === 'round' || !messageMessage) {\n canHaveTail = false;\n }\n \n bubble.classList.add('hide-name', doc.type === 'round' ? 'round' : 'video');\n const storage = this.appMessagesManager.groupedMessagesStorage[message.grouped_id];\n if(message.grouped_id && Object.keys(storage).length !== 1 && albumMustBeRenderedFull) {\n bubble.classList.add('is-album', 'is-grouped');\n \n wrapAlbum({\n groupId: message.grouped_id, \n attachmentDiv,\n middleware: this.getMiddleware(),\n isOut: our,\n lazyLoadQueue: this.lazyLoadQueue,\n chat: this.chat,\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n } else {\n const withTail = !isAndroid && !isApple && doc.type !== 'round' && canHaveTail && !withReplies && USE_MEDIA_TAILS;\n if(withTail) bubble.classList.add('with-media-tail');\n wrapVideo({\n doc, \n container: attachmentDiv, \n message, \n boxWidth: mediaSizes.active.regular.width,\n boxHeight: mediaSizes.active.regular.height, \n withTail, \n isOut,\n lazyLoadQueue: this.lazyLoadQueue,\n middleware: this.getMiddleware(),\n group: CHAT_ANIMATION_GROUP,\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia,\n });\n }\n \n break;\n } else {\n const newNameContainer = wrapGroupedDocuments({\n albumMustBeRenderedFull,\n message,\n bubble,\n messageDiv,\n chat: this.chat,\n loadPromises,\n noAutoDownload: this.chat.noAutoDownloadMedia\n });\n\n if(newNameContainer) {\n nameContainer = newNameContainer;\n }\n\n const lastContainer = messageDiv.lastElementChild.querySelector('.document-message, .document-size, .audio');\n lastContainer && lastContainer.append(timeSpan.cloneNode(true));\n\n bubble.classList.remove('is-message-empty');\n messageDiv.classList.add((doc.type !== 'photo' ? doc.type || 'document' : 'document') + '-message');\n processingWebPage = true;\n \n break;\n }\n\n break;\n }\n\n case 'messageMediaContact': {\n //this.log('wrapping contact', message);\n\n const contactDiv = document.createElement('div');\n contactDiv.classList.add('contact');\n contactDiv.dataset.peerId = '' + messageMedia.user_id;\n\n messageDiv.classList.add('contact-message');\n processingWebPage = true;\n\n const texts = [];\n if(message.media.first_name) texts.push(RichTextProcessor.wrapEmojiText(message.media.first_name));\n if(message.media.last_name) texts.push(RichTextProcessor.wrapEmojiText(message.media.last_name));\n\n contactDiv.innerHTML = `\n <div class=\"contact-details\">\n <div class=\"contact-name\">${texts.join(' ')}</div>\n <div class=\"contact-number\">${message.media.phone_number ? '+' + formatPhoneNumber(message.media.phone_number).formatted : 'Unknown phone number'}</div>\n </div>`;\n\n const avatarElem = new AvatarElement();\n //avatarElem.lazyLoadQueue = this.lazyLoadQueue;\n avatarElem.setAttribute('peer', '' + message.media.user_id);\n avatarElem.classList.add('contact-avatar', 'avatar-54');\n\n contactDiv.prepend(avatarElem);\n\n bubble.classList.remove('is-message-empty');\n messageDiv.classList.add('contact-message');\n messageDiv.append(contactDiv);\n\n break;\n }\n\n case 'messageMediaPoll': {\n bubble.classList.remove('is-message-empty');\n \n const pollElement = wrapPoll(message);\n messageDiv.prepend(pollElement);\n messageDiv.classList.add('poll-message');\n\n break;\n }\n \n default:\n bubble.classList.remove('is-message-empty');\n messageDiv.innerHTML = '<i class=\"media-not-supported\">This message is currently not supported on Telegram Web. Try <a href=\"https://desktop.telegram.org/\" target=\"_blank\">desktop.telegram.org</a></i>';\n messageDiv.append(timeSpan);\n this.log.warn('unrecognized media type:', message.media._, message);\n break;\n }\n \n if(!processingWebPage) {\n bubbleContainer.append(attachmentDiv);\n }\n\n /* if(bubble.classList.contains('is-message-empty') && (bubble.classList.contains('photo') || bubble.classList.contains('video'))) {\n bubble.classList.add('no-tail');\n\n if(!bubble.classList.contains('with-media-tail')) {\n bubble.classList.add('use-border-radius');\n }\n } */\n }\n\n if(this.chat.selection.isSelecting) {\n this.chat.selection.toggleBubbleCheckbox(bubble, true);\n }\n\n let savedFrom = '';\n \n const needName = (peerId < 0 && (peerId !== message.fromId || our)) && message.fromId !== rootScope.myId;\n if(needName || message.fwd_from || message.reply_to_mid) { // chat\n let title: HTMLSpanElement;\n\n const isForwardFromChannel = message.from_id && message.from_id._ === 'peerChannel' && message.fromId === message.fwdFromId;\n \n let isHidden = message.fwd_from && !message.fwd_from.from_id && !message.fwd_from.channel_id;\n if(isHidden) {\n ///////this.log('message to render hidden', message);\n title = document.createElement('span');\n title.innerHTML = RichTextProcessor.wrapEmojiText(message.fwd_from.from_name);\n title.classList.add('peer-title');\n //title = message.fwd_from.from_name;\n bubble.classList.add('hidden-profile');\n } else {\n title = new PeerTitle({peerId: message.fwdFromId || message.fromId}).element;\n }\n \n //this.log(title);\n \n if((message.fwdFromId || message.fwd_from)) {\n if(this.peerId !== rootScope.myId && !isForwardFromChannel) {\n bubble.classList.add('forwarded');\n }\n \n if(message.savedFrom) {\n savedFrom = message.savedFrom;\n }\n \n if(!bubble.classList.contains('sticker')) {\n let nameDiv = document.createElement('div');\n nameDiv.classList.add('name');\n nameDiv.dataset.peerId = message.fwdFromId;\n\n if(this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || isForwardFromChannel) {\n nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fwdFromId, false);\n nameDiv.append(title);\n } else {\n /* const fromTitle = message.fromId === this.myID || appPeersManager.isBroadcast(message.fwdFromId || message.fromId) ? '' : `<div class=\"name\" data-peer-id=\"${message.fromId}\" style=\"color: ${appPeersManager.getPeerColorByID(message.fromId, false)};\">${appPeersManager.getPeerTitle(message.fromId)}</div>`;\n nameDiv.innerHTML = fromTitle + 'Forwarded from ' + title; */\n nameDiv.append(i18n('ForwardedFrom', [title]));\n\n if(savedFrom) {\n nameDiv.dataset.savedFrom = savedFrom;\n }\n }\n \n nameContainer.append(nameDiv);\n }\n } else {\n if(!bubble.classList.contains('sticker') && needName) {\n let nameDiv = document.createElement('div');\n nameDiv.classList.add('name');\n nameDiv.append(title);\n\n if(!our) {\n nameDiv.style.color = this.appPeersManager.getPeerColorById(message.fromId, false);\n }\n\n nameDiv.dataset.peerId = message.fromId;\n nameContainer.append(nameDiv);\n } else /* if(!message.reply_to_mid) */ {\n bubble.classList.add('hide-name');\n }\n }\n\n if(message.reply_to_mid && message.reply_to_mid !== this.chat.threadId) {\n MessageRender.setReply({\n chat: this.chat,\n bubble,\n bubbleContainer,\n message\n });\n }\n \n const needAvatar = this.chat.isAnyGroup() && !isOut;\n if(needAvatar) {\n let avatarElem = new AvatarElement();\n //avatarElem.lazyLoadQueue = this.lazyLoadQueue;\n avatarElem.classList.add('user-avatar', 'avatar-40');\n avatarElem.loadPromises = loadPromises;\n\n if(!message.fwdFromId && message.fwd_from && message.fwd_from.from_name) {\n avatarElem.setAttribute('peer-title', /* '🔥 FF 🔥' */message.fwd_from.from_name);\n }\n\n avatarElem.setAttribute('peer', '' + (((message.fwd_from && (this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID)) || isForwardFromChannel ? message.fwdFromId : message.fromId) || 0));\n //avatarElem.update();\n \n //this.log('exec loadDialogPhoto', message);\n\n contentWrapper.append(avatarElem);\n }\n } else {\n bubble.classList.add('hide-name');\n }\n\n if(this.chat.type === 'pinned') {\n savedFrom = `${this.chat.peerId}_${message.mid}`;\n }\n\n const isThreadStarter = messageWithReplies && messageWithReplies.mid === this.chat.threadId;\n if(isThreadStarter) {\n bubble.classList.add('is-thread-starter', 'is-group-last');\n }\n\n if(savedFrom && (this.chat.type === 'pinned' || message.fwd_from.saved_from_msg_id) && this.peerId !== REPLIES_PEER_ID) {\n const goto = document.createElement('div');\n goto.classList.add('bubble-beside-button', 'goto-original', 'tgico-arrow_next');\n bubbleContainer.append(goto);\n bubble.dataset.savedFrom = savedFrom;\n bubble.classList.add('with-beside-button');\n }\n \n bubble.classList.add(isOut ? 'is-out' : 'is-in');\n if(updatePosition) {\n this.renderMessagesQueue(message, bubble, reverse, loadPromises);\n }\n\n if(withReplies) {\n const isFooter = MessageRender.renderReplies({\n bubble,\n bubbleContainer,\n message: messageWithReplies,\n messageDiv,\n loadPromises\n });\n\n if(isFooter) {\n canHaveTail = true;\n }\n }\n\n if(canHaveTail) {\n bubble.classList.add('can-have-tail');\n\n bubbleContainer.append(generateTail());\n }\n\n return bubble;\n }\n\n public performHistoryResult(history: number[], reverse: boolean, isBackLimit: boolean, additionMsgId?: number) {\n // commented bot getProfile in getHistory!\n if(!history/* .filter((id: number) => id > 0) */.length) {\n if(!isBackLimit) {\n this.scrollable.loadedAll.top = true;\n\n /* if(this.chat.type === 'discussion') {\n const serviceStartMessageId = this.appMessagesManager.threadsServiceMessagesIdsStorage[this.peerId + '_' + this.chat.threadId];\n if(serviceStartMessageId) history.push(serviceStartMessageId);\n history.push(this.chat.threadId);\n } */\n } else {\n this.scrollable.loadedAll.bottom = true;\n }\n }\n\n history = history.slice(); // need\n\n if(additionMsgId) {\n history.unshift(additionMsgId);\n }\n\n /* if(testScroll && additionMsgID) {\n for(let i = 0; i < 3; ++i) {\n let _history = history.slice();\n setTimeout(() => {\n this.performHistoryResult(_history, reverse, isBackLimit, 0, resetPromises);\n }, 0);\n }\n } */\n\n const historyStorage = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId);\n if(history.includes(historyStorage.maxId)) {\n this.scrollable.loadedAll.bottom = true;\n }\n\n //console.time('appImManager render history');\n\n return new Promise<boolean>((resolve, reject) => {\n //await new Promise((resolve) => setTimeout(resolve, 1e3));\n\n /* if(DEBUG) {\n this.log('performHistoryResult: will render some messages:', history.length, this.isHeavyAnimationInProgress, this.messagesQueuePromise);\n } */\n\n const method = (reverse ? history.shift : history.pop).bind(history);\n\n //const padding = 10000;\n //const realLength = this.scrollable.container.childElementCount;\n let previousScrollHeightMinusTop: number/* , previousScrollHeight: number */;\n //if(realLength > 0/* && (reverse || isSafari) */) { // for safari need set when scrolling bottom too\n //if(!this.scrollable.isHeavyScrolling) {\n this.messagesQueueOnRender = () => {\n const {scrollTop, scrollHeight} = this.scrollable;\n\n //previousScrollHeight = scrollHeight;\n //previousScrollHeight = scrollHeight + padding;\n previousScrollHeightMinusTop = reverse ? scrollHeight - scrollTop : scrollTop;\n\n //this.chatInner.style.paddingTop = padding + 'px';\n /* if(reverse) {\n previousScrollHeightMinusTop = this.scrollable.scrollHeight - scrollTop;\n } else {\n previousScrollHeightMinusTop = scrollTop;\n } */\n\n /* if(DEBUG) {\n this.log('performHistoryResult: messagesQueueOnRender, scrollTop:', scrollTop, scrollHeight, previousScrollHeightMinusTop);\n } */\n this.messagesQueueOnRender = undefined;\n };\n //}\n //}\n\n if(this.needReflowScroll) {\n reflowScrollableElement(this.scrollable.container);\n this.needReflowScroll = false;\n }\n\n while(history.length) {\n let message = this.chat.getMessage(method());\n this.renderMessage(message, reverse, true);\n }\n\n (this.messagesQueuePromise || Promise.resolve())\n //.then(() => new Promise(resolve => setTimeout(resolve, 100)))\n .then(() => {\n if(previousScrollHeightMinusTop !== undefined) {\n /* const scrollHeight = this.scrollable.scrollHeight;\n const addedHeight = scrollHeight - previousScrollHeight;\n \n this.chatInner.style.paddingTop = (10000 - addedHeight) + 'px'; */\n /* const scrollHeight = this.scrollable.scrollHeight;\n const addedHeight = scrollHeight - previousScrollHeight;\n \n this.chatInner.style.paddingTop = (padding - addedHeight) + 'px';\n \n //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;\n const newScrollTop = reverse ? scrollHeight - addedHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;\n this.log('performHistoryResult: will set scrollTop', \n previousScrollHeightMinusTop, this.scrollable.scrollHeight, \n newScrollTop, this.scrollable.container.clientHeight); */\n //const newScrollTop = reverse ? scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;\n const newScrollTop = reverse ? this.scrollable.scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop;\n \n /* if(DEBUG) {\n this.log('performHistoryResult: will set up scrollTop:', newScrollTop, this.isHeavyAnimationInProgress);\n } */\n\n // touchSupport for safari iOS\n //isTouchSupported && isApple && (this.scrollable.container.style.overflow = 'hidden');\n this.scrollable.scrollTop = newScrollTop;\n //this.scrollable.scrollTop = this.scrollable.scrollHeight;\n //isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');\n\n if(isSafari/* && !isAppleMobile */) { // * fix blinking and jumping\n reflowScrollableElement(this.scrollable.container);\n }\n\n /* if(DEBUG) {\n this.log('performHistoryResult: have set up scrollTop:', newScrollTop, this.scrollable.scrollTop, this.scrollable.scrollHeight, this.isHeavyAnimationInProgress);\n } */\n }\n\n resolve(true);\n }, reject);\n }).then(() => {\n //console.timeEnd('appImManager render history');\n\n //return new Promise<boolean>((resolve) => setTimeout(() => resolve(true), 300));\n return true;\n });\n }\n\n onDatePick = (timestamp: number) => {\n const peerId = this.peerId;\n this.appMessagesManager.requestHistory(peerId, 0, 2, -1, timestamp, this.chat.threadId).then(history => {\n if(!history?.messages?.length) {\n this.log.error('no history!');\n return;\n } else if(this.peerId !== peerId) {\n return;\n }\n\n this.chat.setMessageId((history.messages[0] as MyMessage).mid);\n //console.log('got history date:', history);\n });\n };\n\n public requestHistory(maxId: number, loadCount: number, backLimit: number) {\n //const middleware = this.getMiddleware();\n if(this.chat.type === 'chat' || this.chat.type === 'discussion') {\n return this.appMessagesManager.getHistory(this.peerId, maxId, loadCount, backLimit, this.chat.threadId);\n } else if(this.chat.type === 'pinned') {\n const promise = this.appMessagesManager.getSearch({\n peerId: this.peerId, \n inputFilter: {_: 'inputMessagesFilterPinned'}, \n maxId, \n limit: loadCount, \n backLimit\n })\n .then(value => ({history: value.history.map(m => m.mid)}));\n\n return promise;\n } else if(this.chat.type === 'scheduled') {\n return this.appMessagesManager.getScheduledMessages(this.peerId).then(mids => {\n this.scrollable.loadedAll.top = true;\n this.scrollable.loadedAll.bottom = true;\n return {history: mids.slice().reverse()};\n });\n }\n }\n\n /**\n * Load and render history\n * @param maxId max message id\n * @param reverse 'true' means up\n * @param isBackLimit is search\n * @param additionMsgId for the last message\n * @param justLoad do not render\n */\n public getHistory(maxId = 0, reverse = false, isBackLimit = false, additionMsgId = 0, justLoad = false): {cached: boolean, promise: Promise<boolean>} {\n const peerId = this.peerId;\n\n //console.time('appImManager call getHistory');\n const pageCount = Math.min(30, this.appPhotosManager.windowH / 38/* * 1.25 */ | 0);\n //const loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;\n const realLoadCount = Object.keys(this.bubbles).length > 0/* || additionMsgId */ ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;\n //const realLoadCount = pageCount;//const realLoadCount = 50;\n let loadCount = realLoadCount;\n \n /* if(TEST_SCROLL) {\n //loadCount = 1;\n if(Object.keys(this.bubbles).length > 0)\n return {cached: false, promise: Promise.resolve(true)};\n } */\n if(TEST_SCROLL !== undefined) {\n if(TEST_SCROLL) {\n if(Object.keys(this.bubbles).length > 0) {\n --TEST_SCROLL;\n }\n } else {\n return {cached: false, promise: Promise.resolve(true)};\n }\n }\n \n ////console.time('render history total');\n \n let backLimit = 0;\n if(isBackLimit) {\n backLimit = loadCount;\n\n if(!reverse) { // if not jump\n loadCount = 0;\n //maxId = this.appMessagesManager.incrementMessageId(maxId, 1);\n }\n }\n\n let additionMsgIds: number[];\n if(additionMsgId && !isBackLimit) {\n if(this.chat.type === 'pinned') {\n additionMsgIds = [additionMsgId];\n } else {\n const historyStorage = this.appMessagesManager.getHistoryStorage(peerId, this.chat.threadId);\n if(historyStorage.history.length < loadCount && !historyStorage.history.slice.isEnd(SliceEnd.Both)) {\n additionMsgIds = historyStorage.history.slice.slice();\n\n // * filter last album, because we don't know is it the last item\n for(let i = additionMsgIds.length - 1; i >= 0; --i) {\n const message = this.chat.getMessage(additionMsgIds[i]);\n if(message.grouped_id) additionMsgIds.splice(i, 1);\n else break;\n }\n\n maxId = additionMsgIds[additionMsgIds.length - 1] || maxId;\n }\n }\n }\n\n /* const result = additionMsgID ? \n {history: [additionMsgID]} : \n appMessagesManager.getHistory(this.peerId, maxId, loadCount, backLimit); */\n let result: ReturnType<AppMessagesManager['getHistory']> | {history: number[]} = this.requestHistory(maxId, loadCount, backLimit) as any;\n let resultPromise: Promise<any>;\n\n //const isFirstMessageRender = !!additionMsgID && result instanceof Promise && !appMessagesManager.getMessage(additionMsgID).grouped_id;\n const isAdditionRender = additionMsgIds?.length && result instanceof Promise;\n const isFirstMessageRender = (this.isFirstLoad && backLimit && result instanceof Promise) || isAdditionRender;\n if(isAdditionRender) {\n resultPromise = result as Promise<any>;\n result = {history: additionMsgIds};\n //additionMsgID = 0;\n }\n\n this.isFirstLoad = false;\n\n const processResult = (historyResult: typeof result) => {\n if(this.chat.type === 'discussion' && 'offsetIdOffset' in historyResult) {\n //this.log('discussion got history', loadCount, backLimit, historyResult, isTopEnd);\n\n // * inject discussion start\n if(historyResult.history.isEnd(SliceEnd.Top)) {\n const serviceStartMessageId = this.appMessagesManager.threadsServiceMessagesIdsStorage[this.peerId + '_' + this.chat.threadId];\n if(serviceStartMessageId) historyResult.history.push(serviceStartMessageId);\n historyResult.history.push(...this.chat.getMidsByMid(this.chat.threadId).reverse());\n this.scrollable.loadedAll.top = true;\n }\n }\n };\n\n const sup = (result: HistoryResult) => {\n /* if(maxId && result.history?.length) {\n if(this.bubbles[maxId]) {\n result.history.findAndSplice(mid => mid === maxId); \n }\n } */\n\n processResult(result);\n \n ////console.timeEnd('render history total');\n \n return getHeavyAnimationPromise().then(() => {\n return this.performHistoryResult(result.history || [], reverse, isBackLimit, !isAdditionRender && additionMsgId);\n });\n };\n\n const processPromise = (result: Promise<HistoryResult>) => {\n const promise = result.then((result) => {\n //this.log('getHistory not cached result by maxId:', maxId, reverse, isBackLimit, result, peerId, justLoad);\n\n if(reverse ? this.getHistoryTopPromise !== promise : this.getHistoryBottomPromise !== promise) {\n this.log.warn('getHistory: peer changed');\n ////console.timeEnd('render history total');\n return Promise.reject();\n }\n\n if(justLoad) {\n this.scrollable.onScroll(); // нужно делать из-за ранней прогрузки\n return true;\n }\n //console.timeEnd('appImManager call getHistory');\n\n return sup(result);\n }, (err) => {\n this.log.error('getHistory error:', err);\n throw err;\n });\n \n return promise;\n };\n\n let promise: Promise<boolean>, cached: boolean;\n if(result instanceof Promise) {\n cached = false;\n promise = processPromise(result);\n } else if(justLoad) {\n return null;\n } else {\n cached = true;\n //this.log('getHistory cached result by maxId:', maxId, reverse, isBackLimit, result, peerId, justLoad);\n promise = sup(result as HistoryResult);\n //return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);\n //return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);\n }\n\n const waitPromise = isAdditionRender ? processPromise(resultPromise) : promise;\n\n if(isFirstMessageRender && rootScope.settings.animationsEnabled/* && false */) {\n let times = isAdditionRender ? 2 : 1;\n this.messagesQueueOnRenderAdditional = () => {\n this.log('ship went past rocks of magnets');\n\n if(--times) return;\n\n this.messagesQueueOnRenderAdditional = undefined;\n if(!Object.keys(this.bubbles).length) {\n return;\n }\n\n let sortedMids = getObjectKeysAndSort(this.bubbles, 'desc');\n\n if(isAdditionRender && additionMsgIds.length) {\n sortedMids = sortedMids.filter(mid => !additionMsgIds.includes(mid));\n }\n\n let targetMid: number;\n if(backLimit) {\n targetMid = maxId || Math.max(...sortedMids); // * on discussion enter\n } else {\n if(additionMsgId) {\n targetMid = additionMsgId;\n } else { // * if maxId === 0\n targetMid = Math.max(...sortedMids);\n }\n }\n\n const topIds = sortedMids.slice(sortedMids.findIndex(mid => targetMid > mid));\n const middleIds = isAdditionRender ? [] : [targetMid];\n const bottomIds = isAdditionRender ? [] : sortedMids.slice(0, sortedMids.findIndex(mid => targetMid >= mid)).reverse();\n \n if(DEBUG) {\n this.log('getHistory: targeting mid:', targetMid, maxId, additionMsgId, \n topIds.map(m => this.appMessagesManager.getServerMessageId(m)), \n bottomIds.map(m => this.appMessagesManager.getServerMessageId(m)));\n }\n\n const setBubbles: HTMLElement[] = [];\n\n this.chatInner.classList.add('zoom-fading');\n const delay = isAdditionRender ? 10 : 40;\n const offsetIndex = isAdditionRender ? 0 : 1;\n const animateAsLadder = (mids: number[], offsetIndex = 0) => {\n const animationPromise = deferredPromise<void>();\n let lastMsDelay = 0;\n mids.forEach((mid, idx) => {\n if(!this.bubbles[mid]) {\n this.log.warn('animateAsLadder: no bubble by mid:', mid);\n return;\n }\n\n const contentWrapper = this.bubbles[mid].lastElementChild as HTMLElement;\n\n lastMsDelay = ((idx + offsetIndex) || 0.1) * delay;\n //lastMsDelay = (idx + offsetIndex) * delay;\n //lastMsDelay = (idx || 0.1) * 1000;\n \n contentWrapper.classList.add('zoom-fade');\n contentWrapper.style.transitionDelay = lastMsDelay + 'ms';\n\n if(idx === (mids.length - 1)) {\n const onTransitionEnd = (e: TransitionEvent) => {\n if(e.target !== contentWrapper) {\n return;\n }\n\n animationPromise.resolve();\n contentWrapper.removeEventListener('transitionend', onTransitionEnd);\n };\n \n contentWrapper.addEventListener('transitionend', onTransitionEnd);\n }\n \n //this.log('supa', bubble);\n\n setBubbles.push(contentWrapper);\n });\n\n if(!mids.length) {\n animationPromise.resolve();\n }\n\n return {lastMsDelay, animationPromise};\n };\n\n const topRes = animateAsLadder(topIds, offsetIndex);\n const middleRes = animateAsLadder(middleIds);\n const bottomRes = animateAsLadder(bottomIds, offsetIndex);\n const promises = [topRes.animationPromise, middleRes.animationPromise, bottomRes.animationPromise];\n const delays: number[] = [topRes.lastMsDelay, middleRes.lastMsDelay, bottomRes.lastMsDelay];\n\n fastRaf(() => {\n setBubbles.forEach(contentWrapper => {\n contentWrapper.classList.remove('zoom-fade');\n });\n });\n\n let promise: Promise<any>;\n if(topIds.length || middleIds.length || bottomIds.length) {\n promise = Promise.all(promises);\n\n dispatchHeavyAnimationEvent(promise, Math.max(...delays) + 200) // * 200 - transition time\n .then(() => { \n fastRaf(() => {\n setBubbles.forEach(contentWrapper => {\n contentWrapper.style.transitionDelay = '';\n });\n\n this.chatInner.classList.remove('zoom-fading');\n });\n\n // ! в хроме, каким-то образом из-за zoom-fade класса начинает прыгать скролл при подгрузке сообщений вверх, \n // ! т.е. скролл не ставится, так же, как в сафари при translateZ на блок выше scrollable\n if(!isSafari) {\n this.needReflowScroll = true;\n }\n });\n }\n\n (promise || Promise.resolve()).then(() => {\n setTimeout(() => { // preload messages\n this.loadMoreHistory(reverse, true);\n }, 0);\n });\n };\n } else {\n this.messagesQueueOnRenderAdditional = undefined;\n }\n\n (reverse ? this.getHistoryTopPromise = waitPromise : this.getHistoryBottomPromise = waitPromise);\n waitPromise.then(() => {\n (reverse ? this.getHistoryTopPromise = undefined : this.getHistoryBottomPromise = undefined);\n });\n\n if(justLoad) {\n return null;\n }\n\n /* false && */!isFirstMessageRender && promise.then(() => {\n if(reverse) {\n this.loadedTopTimes++;\n this.loadedBottomTimes = Math.max(0, --this.loadedBottomTimes);\n } else {\n this.loadedBottomTimes++;\n this.loadedTopTimes = Math.max(0, --this.loadedTopTimes);\n }\n\n let ids: number[];\n if((reverse && this.loadedTopTimes > 2) || (!reverse && this.loadedBottomTimes > 2)) {\n ids = getObjectKeysAndSort(this.bubbles);\n }\n\n //let removeCount = loadCount / 2;\n const safeCount = realLoadCount * 2; // cause i've been runningrunningrunning all day\n //this.log('getHistory: slice loadedTimes:', reverse, pageCount, this.loadedTopTimes, this.loadedBottomTimes, ids?.length, safeCount);\n if(ids && ids.length > safeCount) {\n if(reverse) {\n //ids = ids.slice(-removeCount);\n //ids = ids.slice(removeCount * 2);\n ids = ids.slice(safeCount);\n this.scrollable.loadedAll.bottom = false;\n\n //this.log('getHistory: slice bottom messages:', ids.length, loadCount);\n //this.getHistoryBottomPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд\n } else {\n //ids = ids.slice(0, removeCount);\n //ids = ids.slice(0, ids.length - (removeCount * 2));\n ids = ids.slice(0, ids.length - safeCount);\n this.scrollable.loadedAll.top = false;\n\n //this.log('getHistory: slice up messages:', ids.length, loadCount);\n //this.getHistoryTopPromise = undefined; // !WARNING, это нужно для обратной загрузки истории, если запрос словил флуд\n }\n\n //this.log('getHistory: will slice ids:', ids, reverse);\n\n this.deleteMessagesByIds(ids, false);\n }\n });\n\n promise.then(() => {\n // preload more\n //if(!isFirstMessageRender) {\n if(this.chat.type === 'chat'/* || this.chat.type === 'discussion' */) {\n /* const storage = this.appMessagesManager.getHistoryStorage(peerId, this.chat.threadId);\n const isMaxIdInHistory = storage.history.indexOf(maxId) !== -1;\n if(isMaxIdInHistory || true) { // * otherwise it is a search or jump */\n setTimeout(() => {\n if(reverse) {\n this.loadMoreHistory(true, true);\n } else {\n this.loadMoreHistory(false, true);\n }\n }, 0);\n //}\n }\n //}\n });\n\n return {cached, promise};\n }\n\n public setUnreadDelimiter() {\n if(!(this.chat.type === 'chat' || this.chat.type === 'discussion')) {\n return;\n }\n\n if(this.attachedUnreadBubble) {\n return;\n }\n\n const historyStorage = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId);\n let readMaxId = this.appMessagesManager.getReadMaxIdIfUnread(this.peerId, this.chat.threadId);\n if(!readMaxId) return;\n\n readMaxId = Object.keys(this.bubbles)\n .filter(mid => !this.bubbles[mid].classList.contains('is-out'))\n .map(i => +i)\n .sort((a, b) => a - b)\n .find(i => i > readMaxId);\n\n if(readMaxId && this.bubbles[readMaxId]) {\n let bubble = this.bubbles[readMaxId];\n if(this.firstUnreadBubble && this.firstUnreadBubble !== bubble) {\n this.firstUnreadBubble.classList.remove('is-first-unread');\n this.firstUnreadBubble = null;\n }\n\n if(readMaxId !== historyStorage.maxId) {\n bubble.classList.add('is-first-unread');\n }\n\n this.firstUnreadBubble = bubble;\n this.attachedUnreadBubble = true;\n }\n }\n\n public deleteEmptyDateGroups() {\n const mustBeCount = 1 + +!!this.stickyIntersector;\n for(const i in this.dateMessages) {\n const dateMessage = this.dateMessages[i];\n\n if(dateMessage.container.childElementCount === mustBeCount) { // only date div + sentinel div\n dateMessage.container.remove();\n if(this.stickyIntersector) {\n this.stickyIntersector.unobserve(dateMessage.container, dateMessage.div);\n }\n delete this.dateMessages[i];\n }\n }\n }\n}\n\nexport function generateTail() {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttributeNS(null, 'viewBox', '0 0 11 20');\n svg.setAttributeNS(null, 'width', '11');\n svg.setAttributeNS(null, 'height', '20');\n svg.classList.add('bubble-tail');\n\n const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');\n use.setAttributeNS(null, 'href', '#message-tail-filled');\n\n svg.append(use);\n\n return svg;\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appChatsManager from \"../../lib/appManagers/appChatsManager\";\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport rootScope from \"../../lib/rootScope\";\nimport { addCancelButton, PopupButton } from \".\";\nimport PopupPeer from \"./peer\";\nimport { ChatType } from \"../chat/chat\";\nimport { i18n, LangPackKey } from \"../../lib/langPack\";\nimport PeerTitle from \"../peerTitle\";\n\nexport default class PopupDeleteMessages {\n constructor(peerId: number, mids: number[], type: ChatType, onConfirm?: () => void) {\n const peerTitleElement = new PeerTitle({\n peerId,\n onlyFirstName: true\n }).element;\n\n mids = mids.slice();\n const callback = (revoke?: true) => {\n onConfirm && onConfirm();\n if(type === 'scheduled') {\n appMessagesManager.deleteScheduledMessages(peerId, mids);\n } else {\n appMessagesManager.deleteMessages(peerId, mids, revoke);\n }\n };\n\n let title: LangPackKey, titleArgs: any[], description: LangPackKey, descriptionArgs: any[], buttons: PopupButton[];\n if(mids.length === 1) {\n title = 'DeleteSingleMessagesTitle';\n } else {\n title = 'DeleteMessagesTitle';\n titleArgs = [i18n('messages', [mids.length])];\n }\n \n description = mids.length === 1 ? 'AreYouSureDeleteSingleMessage' : 'AreYouSureDeleteFewMessages';\n\n buttons = [{\n langKey: 'Delete',\n isDanger: true,\n callback: () => callback()\n }];\n\n if(peerId === rootScope.myId || type === 'scheduled') {\n \n } else {\n if(peerId > 0) {\n buttons.push({\n langKey: 'DeleteMessagesOptionAlso',\n langArgs: [peerTitleElement],\n isDanger: true,\n callback: () => callback(true)\n });\n } else {\n const chat = appChatsManager.getChat(-peerId);\n\n const hasRights = appChatsManager.hasRights(-peerId, 'delete_messages');\n if(chat._ === 'chat') {\n const canRevoke = hasRights ? mids.slice() : mids.filter(mid => {\n const message = appMessagesManager.getMessageByPeer(peerId, mid);\n return message.fromId === rootScope.myId;\n });\n\n if(canRevoke.length) {\n if(canRevoke.length === mids.length) {\n buttons.push({\n langKey: 'DeleteForAll',\n isDanger: true,\n callback: () => callback(true)\n });\n } else {\n buttons.push({\n langKey: 'DeleteMessagesOption',\n isDanger: true,\n callback: () => callback(true)\n });\n\n description = 'DeleteMessagesTextGroup';\n descriptionArgs = [i18n('messages', [canRevoke.length])];\n //description = `You can also delete the ${canRevoke.length} message${canRevoke.length > 1 ? 's' : ''} you sent from the inboxes of other group members by pressing \"${buttonText}\".`;\n }\n }\n } else {\n buttons[0].callback = () => callback(true);\n }\n }\n }\n\n addCancelButton(buttons);\n\n const popup = new PopupPeer('popup-delete-chat', {\n peerId,\n titleLangKey: title,\n titleLangArgs: titleArgs,\n descriptionLangKey: description,\n descriptionLangArgs: descriptionArgs,\n buttons\n });\n\n popup.show();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport { addCancelButton, PopupButton } from \".\";\nimport PopupPeer from \"./peer\";\nimport appPeersManager from \"../../lib/appManagers/appPeersManager\";\nimport rootScope from \"../../lib/rootScope\";\nimport { LangPackKey } from \"../../lib/langPack\";\nimport appChatsManager from \"../../lib/appManagers/appChatsManager\";\nimport PeerTitle from \"../peerTitle\";\n\nexport default class PopupPinMessage {\n constructor(peerId: number, mid: number, unpin?: true, onConfirm?: () => void) {\n let title: LangPackKey, description: LangPackKey, buttons: PopupButton[] = [];\n\n const canUnpin = appPeersManager.canPinMessage(peerId);\n\n const callback = (oneSide?: true, silent?: true) => {\n setTimeout(() => { // * костыль, потому что document.elementFromPoint вернёт popup-peer пока он будет закрываться\n let promise: Promise<any>;\n if(unpin && !mid) {\n if(canUnpin) {\n promise = appMessagesManager.unpinAllMessages(peerId);\n } else {\n promise = appMessagesManager.hidePinnedMessages(peerId);\n }\n } else {\n promise = appMessagesManager.updatePinnedMessage(peerId, mid, unpin, silent, oneSide);\n }\n\n if(onConfirm) {\n promise.then(onConfirm);\n }\n }, 300);\n };\n\n if(unpin) {\n let buttonText: LangPackKey = 'UnpinMessage';\n if(!mid) {\n if(canUnpin) {\n title = 'Popup.Unpin.AllTitle';\n description = 'Chat.UnpinAllMessagesConfirmation';\n } else {\n title = 'Popup.Unpin.HideTitle';\n description = 'Popup.Unpin.HideDescription';\n buttonText = 'Popup.Unpin.Hide';\n }\n } else {\n title = 'UnpinMessageAlertTitle';\n description = 'Chat.Confirm.Unpin';\n }\n \n buttons.push({\n langKey: buttonText,\n isDanger: true,\n callback: () => callback()\n });\n } else {\n title = 'PinMessageAlertTitle';\n const pinButtonText: LangPackKey = 'PinMessage';\n \n if(peerId < 0) {\n buttons.push({\n langKey: pinButtonText,\n callback: () => callback()\n });\n\n if(appChatsManager.isBroadcast(-peerId)) {\n description = 'PinMessageAlertChannel';\n } else {\n description = 'PinMessageAlert';\n \n buttons.push({\n langKey: 'PinNotify',\n callback: () => callback(undefined, true)\n });\n }\n } else {\n description = 'PinMessageAlertChat';\n\n if(peerId === rootScope.myId) {\n buttons.push({\n langKey: pinButtonText,\n callback: () => callback()\n });\n } else {\n buttons.push({\n langKey: pinButtonText,\n callback: () => callback(true)\n });\n \n buttons.push({\n langKey: 'PinAlsoFor',\n langArgs: [new PeerTitle({peerId, onlyFirstName: true}).element],\n callback: () => callback()\n });\n }\n }\n }\n\n addCancelButton(buttons);\n\n const popup = new PopupPeer('popup-delete-chat', {\n peerId,\n titleLangKey: title,\n descriptionLangKey: description,\n buttons\n });\n\n popup.show();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appMessagesManager from \"../../lib/appManagers/appMessagesManager\";\nimport { PopupButton } from \".\";\nimport PopupPeer from \"./peer\";\n\nexport default class PopupSendNow {\n constructor(peerId: number, mids: number[], onConfirm?: () => void) {\n let title: string, description: string, buttons: PopupButton[] = [];\n\n title = `Send Message${mids.length > 1 ? 's' : ''} Now`;\n description = mids.length > 1 ? 'Send ' + mids.length + ' messages now?' : 'Send message now?';\n\n const callback = () => {\n onConfirm && onConfirm();\n appMessagesManager.sendScheduledMessages(peerId, mids);\n };\n\n buttons.push({\n text: 'SEND',\n callback\n });\n\n buttons.push({\n text: 'CANCEL',\n isCancel: true\n });\n\n const popup = new PopupPeer('popup-delete-chat', {\n peerId,\n title,\n description,\n buttons\n });\n\n popup.show();\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppChatsManager } from \"../../lib/appManagers/appChatsManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type { AppPollsManager, Poll } from \"../../lib/appManagers/appPollsManager\";\nimport type Chat from \"./chat\";\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport { attachClickEvent, cancelEvent, cancelSelection, isSelectionEmpty } from \"../../helpers/dom\";\nimport ButtonMenu, { ButtonMenuItemOptions } from \"../buttonMenu\";\nimport { attachContextMenuListener, openBtnMenu, positionMenu } from \"../misc\";\nimport PopupDeleteMessages from \"../popups/deleteMessages\";\nimport PopupForward from \"../popups/forward\";\nimport PopupPinMessage from \"../popups/unpinMessage\";\nimport { copyTextToClipboard } from \"../../helpers/clipboard\";\nimport PopupSendNow from \"../popups/sendNow\";\nimport { toast } from \"../toast\";\nimport I18n, { LangPackKey } from \"../../lib/langPack\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\n\nexport default class ChatContextMenu {\n private buttons: (ButtonMenuItemOptions & {verify: () => boolean, notDirect?: () => boolean, withSelection?: true})[];\n private element: HTMLElement;\n\n private isSelectable: boolean;\n private target: HTMLElement;\n private isTargetAGroupedItem: boolean;\n private isTextSelected: boolean;\n private isAnchorTarget: boolean;\n public peerId: number;\n public mid: number;\n public message: any;\n\n constructor(private attachTo: HTMLElement, private chat: Chat, private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appPollsManager: AppPollsManager) {\n const onContextMenu = (e: MouseEvent | Touch | TouchEvent) => {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n let bubble: HTMLElement, contentWrapper: HTMLElement;\n\n try {\n contentWrapper = findUpClassName(e.target, 'bubble-content-wrapper');\n bubble = contentWrapper ? contentWrapper.parentElement : findUpClassName(e.target, 'bubble');\n } catch(e) {}\n\n // ! context menu click by date bubble (there is no pointer-events)\n if(!bubble) return;\n\n if(e instanceof MouseEvent || e.hasOwnProperty('preventDefault')) (e as any).preventDefault();\n if(this.element.classList.contains('active')) {\n return false;\n }\n if(e instanceof MouseEvent || e.hasOwnProperty('cancelBubble')) (e as any).cancelBubble = true;\n\n let mid = +bubble.dataset.mid;\n if(!mid) return;\n\n // * если открыть контекстное меню для альбома не по бабблу, и последний элемент не выбран, чтобы показать остальные пункты\n if(chat.selection.isSelecting && !contentWrapper) {\n const mids = this.chat.getMidsByMid(mid);\n if(mids.length > 1) {\n const selectedMid = chat.selection.selectedMids.has(mid) ? mid : mids.find(mid => chat.selection.selectedMids.has(mid));\n if(selectedMid) {\n mid = selectedMid;\n }\n }\n }\n\n this.isSelectable = this.chat.selection.canSelectBubble(bubble);\n this.peerId = this.chat.peerId;\n //this.msgID = msgID;\n this.target = e.target as HTMLElement;\n this.isTextSelected = !isSelectionEmpty();\n this.isAnchorTarget = this.target.tagName === 'A' && (this.target as HTMLAnchorElement).target === '_blank';\n\n const groupedItem = findUpClassName(this.target, 'grouped-item');\n this.isTargetAGroupedItem = !!groupedItem;\n if(groupedItem) {\n this.mid = +groupedItem.dataset.mid;\n } else {\n this.mid = mid;\n }\n\n this.message = this.chat.getMessage(this.mid);\n\n this.buttons.forEach(button => {\n let good: boolean;\n\n //if((appImManager.chatSelection.isSelecting && !button.withSelection) || (button.withSelection && !appImManager.chatSelection.isSelecting)) {\n if(chat.selection.isSelecting && !button.withSelection) {\n good = false;\n } else {\n good = contentWrapper || isTouchSupported ? \n button.verify() : \n button.notDirect && button.verify() && button.notDirect();\n }\n\n button.element.classList.toggle('hide', !good);\n });\n\n const side: 'left' | 'right' = bubble.classList.contains('is-in') ? 'left' : 'right';\n //bubble.parentElement.append(this.element);\n //appImManager.log('contextmenu', e, bubble, side);\n positionMenu((e as TouchEvent).touches ? (e as TouchEvent).touches[0] : e as MouseEvent, this.element, side);\n openBtnMenu(this.element, () => {\n this.peerId = this.mid = 0;\n this.target = null;\n });\n };\n\n if(isTouchSupported/* && false */) {\n attachClickEvent(attachTo, (e) => {\n if(chat.selection.isSelecting) {\n return;\n }\n\n const className = (e.target as HTMLElement).className;\n if(!className || !className.includes) return;\n\n chat.log('touchend', e);\n\n const good = ['bubble', 'bubble-content-wrapper', 'bubble-content', 'message', 'time', 'inner'].find(c => className.match(new RegExp(c + '($|\\\\s)')));\n if(good) {\n cancelEvent(e);\n //onContextMenu((e as TouchEvent).changedTouches[0]);\n onContextMenu((e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0] : e as MouseEvent);\n }\n }, {listenerSetter: this.chat.bubbles.listenerSetter});\n\n attachContextMenuListener(attachTo, (e) => {\n if(chat.selection.isSelecting) return;\n\n // * these two lines will fix instant text selection on iOS Safari\n document.body.classList.add('no-select'); // * need no-select on body because chat-input transforms in channels\n attachTo.addEventListener('touchend', (e) => {\n cancelEvent(e); // ! this one will fix propagation to document loader button, etc\n document.body.classList.remove('no-select');\n\n //this.chat.bubbles.onBubblesClick(e);\n }, {once: true, capture: true});\n\n cancelSelection();\n //cancelEvent(e as any);\n const bubble = findUpClassName(e.target, 'grouped-item') || findUpClassName(e.target, 'bubble');\n if(bubble) {\n chat.selection.toggleByBubble(bubble);\n }\n }, this.chat.bubbles.listenerSetter);\n } else attachContextMenuListener(attachTo, onContextMenu, this.chat.bubbles.listenerSetter);\n }\n\n private init() {\n this.buttons = [{\n icon: 'send2',\n text: 'Chat.Context.Scheduled.SendNow',\n onClick: this.onSendScheduledClick,\n verify: () => this.chat.type === 'scheduled' && !this.message.pFlags.is_outgoing\n }, {\n icon: 'send2',\n text: 'Message.Context.Selection.SendNow',\n onClick: this.onSendScheduledClick,\n verify: () => this.chat.type === 'scheduled' && this.chat.selection.selectedMids.has(this.mid) && !this.chat.selection.selectionSendNowBtn.hasAttribute('disabled'),\n notDirect: () => true,\n withSelection: true\n }, {\n icon: 'schedule',\n text: 'Chat.Context.Scheduled.Reschedule',\n onClick: () => {\n this.chat.input.scheduleSending(() => {\n this.appMessagesManager.editMessage(this.message, this.message.message, {\n scheduleDate: this.chat.input.scheduleDate,\n entities: this.message.entities\n });\n\n this.chat.input.onMessageSent(false, false);\n }, new Date(this.message.date * 1000));\n },\n verify: () => this.chat.type === 'scheduled'\n }, {\n icon: 'reply',\n text: 'Reply',\n onClick: this.onReplyClick,\n verify: () => (this.peerId > 0 || this.appChatsManager.hasRights(-this.peerId, 'send_messages')) && \n !this.message.pFlags.is_outgoing && \n !!this.chat.input.messageInput && \n this.chat.type !== 'scheduled'/* ,\n cancelEvent: true */\n }, {\n icon: 'edit',\n text: 'Edit',\n onClick: this.onEditClick,\n verify: () => this.appMessagesManager.canEditMessage(this.message, 'text') && !!this.chat.input.messageInput\n }, {\n icon: 'copy',\n text: 'Copy',\n onClick: this.onCopyClick,\n verify: () => !!this.message.message && !this.isTextSelected\n }, {\n icon: 'copy',\n text: 'Chat.CopySelectedText',\n onClick: this.onCopyClick,\n verify: () => !!this.message.message && this.isTextSelected\n }, {\n icon: 'copy',\n text: 'Message.Context.Selection.Copy',\n onClick: this.onCopyClick,\n verify: () => this.chat.selection.selectedMids.has(this.mid) && !![...this.chat.selection.selectedMids].find(mid => !!this.chat.getMessage(mid).message),\n notDirect: () => true,\n withSelection: true\n }, {\n icon: 'copy',\n text: 'CopyLink',\n onClick: this.onCopyAnchorLinkClick,\n verify: () => this.isAnchorTarget,\n withSelection: true\n }, {\n icon: 'link',\n text: 'CopyLink',\n onClick: this.onCopyLinkClick,\n verify: () => this.appPeersManager.isChannel(this.peerId) && !this.message.pFlags.is_outgoing\n }, {\n icon: 'pin',\n text: 'Message.Context.Pin',\n onClick: this.onPinClick,\n verify: () => !this.message.pFlags.is_outgoing && \n this.message._ !== 'messageService' && \n !this.message.pFlags.pinned && \n this.appPeersManager.canPinMessage(this.peerId) && \n this.chat.type !== 'scheduled',\n }, {\n icon: 'unpin',\n text: 'Message.Context.Unpin',\n onClick: this.onUnpinClick,\n verify: () => this.message.pFlags.pinned && this.appPeersManager.canPinMessage(this.peerId),\n }, {\n icon: 'checkretract',\n text: 'Chat.Poll.Unvote',\n onClick: this.onRetractVote,\n verify: () => {\n const poll = this.message.media?.poll as Poll;\n return poll && poll.chosenIndexes.length && !poll.pFlags.closed && !poll.pFlags.quiz;\n }/* ,\n cancelEvent: true */\n }, {\n icon: 'stop',\n text: 'Chat.Poll.Stop',\n onClick: this.onStopPoll,\n verify: () => {\n const poll = this.message.media?.poll;\n return this.appMessagesManager.canEditMessage(this.message, 'poll') && poll && !poll.pFlags.closed && !this.message.pFlags.is_outgoing;\n }/* ,\n cancelEvent: true */\n }, {\n icon: 'forward',\n text: 'Forward',\n onClick: this.onForwardClick,\n verify: () => this.chat.type !== 'scheduled' && !this.message.pFlags.is_outgoing && this.message._ !== 'messageService'\n }, {\n icon: 'forward',\n text: 'Message.Context.Selection.Forward',\n onClick: this.onForwardClick,\n verify: () => this.chat.selection.selectionForwardBtn && \n this.chat.selection.selectedMids.has(this.mid) && \n !this.chat.selection.selectionForwardBtn.hasAttribute('disabled'),\n notDirect: () => true,\n withSelection: true\n }, {\n icon: 'select',\n text: 'Message.Context.Select',\n onClick: this.onSelectClick,\n verify: () => !this.message.action && !this.chat.selection.selectedMids.has(this.mid) && this.isSelectable,\n notDirect: () => true,\n withSelection: true\n }, {\n icon: 'select',\n text: 'Message.Context.Selection.Clear',\n onClick: this.onClearSelectionClick,\n verify: () => this.chat.selection.selectedMids.has(this.mid),\n notDirect: () => true,\n withSelection: true\n }, {\n icon: 'delete danger',\n text: 'Delete',\n onClick: this.onDeleteClick,\n verify: () => this.appMessagesManager.canDeleteMessage(this.message)\n }, {\n icon: 'delete danger',\n text: 'Message.Context.Selection.Delete',\n onClick: this.onDeleteClick,\n verify: () => this.chat.selection.selectedMids.has(this.mid) && !this.chat.selection.selectionDeleteBtn.hasAttribute('disabled'),\n notDirect: () => true,\n withSelection: true\n }];\n\n this.element = ButtonMenu(this.buttons, this.chat.bubbles.listenerSetter);\n this.element.id = 'bubble-contextmenu';\n this.element.classList.add('contextmenu');\n this.chat.container.append(this.element);\n };\n\n private onSendScheduledClick = () => {\n if(this.chat.selection.isSelecting) {\n this.chat.selection.selectionSendNowBtn.click();\n } else {\n new PopupSendNow(this.peerId, this.chat.getMidsByMid(this.mid));\n }\n };\n\n private onReplyClick = () => {\n this.chat.input.initMessageReply(this.mid);\n };\n\n private onEditClick = () => {\n this.chat.input.initMessageEditing(this.mid);\n };\n\n private onCopyClick = () => {\n if(isSelectionEmpty()) {\n const mids = this.chat.selection.isSelecting ? [...this.chat.selection.selectedMids] : [this.mid];\n const str = mids.reduce((acc, mid) => {\n const message = this.chat.getMessage(mid);\n return acc + (message?.message ? message.message + '\\n' : '');\n }, '').trim();\n copyTextToClipboard(str);\n } else {\n document.execCommand('copy');\n //cancelSelection();\n }\n };\n\n private onCopyAnchorLinkClick = () => {\n copyTextToClipboard((this.target as HTMLAnchorElement).href);\n };\n\n private onCopyLinkClick = () => {\n const username = this.appPeersManager.getPeerUsername(this.peerId);\n const msgId = this.appMessagesManager.getServerMessageId(this.mid);\n let url = 'https://t.me/';\n let key: LangPackKey;\n if(username) {\n url += username + '/' + msgId;\n key = 'LinkCopied';\n } else {\n url += 'c/' + Math.abs(this.peerId) + '/' + msgId;\n key = 'LinkCopiedPrivateInfo';\n }\n\n toast(I18n.format(key, true));\n\n copyTextToClipboard(url);\n };\n\n private onPinClick = () => {\n new PopupPinMessage(this.peerId, this.mid);\n };\n\n private onUnpinClick = () => {\n new PopupPinMessage(this.peerId, this.mid, true);\n };\n\n private onRetractVote = () => {\n this.appPollsManager.sendVote(this.message, []);\n };\n\n private onStopPoll = () => {\n this.appPollsManager.stopPoll(this.message);\n };\n\n private onForwardClick = () => {\n if(this.chat.selection.isSelecting) {\n this.chat.selection.selectionForwardBtn.click();\n } else {\n new PopupForward(this.peerId, this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid));\n }\n };\n\n private onSelectClick = () => {\n this.chat.selection.toggleByBubble(findUpClassName(this.target, 'grouped-item') || findUpClassName(this.target, 'bubble'));\n };\n\n private onClearSelectionClick = () => {\n this.chat.selection.cancelSelection();\n };\n\n private onDeleteClick = () => {\n if(this.chat.selection.isSelecting) {\n this.chat.selection.selectionDeleteBtn.click();\n } else {\n new PopupDeleteMessages(this.peerId, this.isTargetAGroupedItem ? [this.mid] : this.chat.getMidsByMid(this.mid), this.chat.type);\n }\n };\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { EmoticonsDropdown, EmoticonsTab } from \"..\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\nimport { fastRaf } from \"../../../helpers/schedulers\";\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport appStateManager from \"../../../lib/appManagers/appStateManager\";\nimport Config from \"../../../lib/config\";\nimport { i18n, LangPackKey } from \"../../../lib/langPack\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport rootScope from \"../../../lib/rootScope\";\nimport { putPreloader } from \"../../misc\";\nimport Scrollable from \"../../scrollable\";\nimport StickyIntersector from \"../../stickyIntersector\";\n\nexport default class EmojiTab implements EmoticonsTab {\n public content: HTMLElement;\n\n private recent: string[] = [];\n private recentItemsDiv: HTMLElement;\n\n private scroll: Scrollable;\n private stickyIntersector: StickyIntersector;\n\n private loadedURLs: Set<string> = new Set();\n\n init() {\n this.content = document.getElementById('content-emoji') as HTMLDivElement;\n\n const categories: LangPackKey[] = [\n 'Emoji.SmilesAndPeople', \n 'Emoji.AnimalsAndNature', \n 'Emoji.FoodAndDrink', \n 'Emoji.TravelAndPlaces', \n 'Emoji.ActivityAndSport', \n 'Emoji.Objects', \n /* 'Emoji.Symbols', */\n 'Emoji.Flags', \n 'Skin Tones' as any\n ];\n const divs: {\n [category in LangPackKey]?: HTMLDivElement\n } = {};\n\n const sorted: Map<LangPackKey, string[]> = new Map([\n [\n 'Emoji.Recent',\n []\n ]\n ]);\n\n for(const emoji in Config.Emoji) {\n const details = Config.Emoji[emoji];\n const i = '' + details;\n const category = categories[+i[0] - 1];\n if(!category) continue; // maybe it's skin tones\n\n let s = sorted.get(category);\n if(!s) {\n s = [];\n sorted.set(category, s);\n }\n \n s[+i.slice(1) || 0] = emoji;\n }\n\n //console.log('emoticons sorted:', sorted);\n\n //Object.keys(sorted).forEach(c => sorted[c].sort((a, b) => a - b));\n\n sorted.delete(categories.pop());\n\n //console.time('emojiParse');\n sorted.forEach((emojis, category) => {\n const div = document.createElement('div');\n div.classList.add('emoji-category');\n\n const titleDiv = document.createElement('div');\n titleDiv.classList.add('category-title');\n titleDiv.append(i18n(category));\n\n const itemsDiv = document.createElement('div');\n itemsDiv.classList.add('category-items');\n\n div.append(titleDiv, itemsDiv);\n\n emojis.forEach(emoji => {\n /* if(emojiUnicode(emoji) === '1f481-200d-2642') {\n console.log('append emoji', emoji, emojiUnicode(emoji));\n } */\n\n emoji = emoji.split('-').reduce((prev, curr) => prev + String.fromCodePoint(parseInt(curr, 16)), '');\n\n this.appendEmoji(emoji/* .replace(/[\\ufe0f\\u2640\\u2642\\u2695]/g, '') */, itemsDiv, false/* , false */);\n\n /* if(category === 'Smileys & Emotion') {\n console.log('appended emoji', emoji, itemsDiv.children[itemsDiv.childElementCount - 1].innerHTML, emojiUnicode(emoji));\n } */\n });\n\n divs[category] = div;\n });\n\n //console.timeEnd('emojiParse');\n\n const menu = this.content.previousElementSibling as HTMLElement;\n const emojiScroll = this.scroll = new Scrollable(this.content, 'EMOJI');\n\n //emojiScroll.setVirtualContainer(emojiScroll.container);\n\n const preloader = putPreloader(this.content, true);\n\n Promise.all([\n new Promise((resolve) => setTimeout(resolve, 200)),\n\n appStateManager.getState().then(state => {\n if(Array.isArray(state.recentEmoji)) {\n this.recent = state.recentEmoji;\n }\n })\n ]).then(() => {\n preloader.remove();\n\n this.recentItemsDiv = divs['Emoji.Recent'].querySelector('.category-items');\n for(const emoji of this.recent) {\n this.appendEmoji(emoji, this.recentItemsDiv);\n }\n\n this.recentItemsDiv.parentElement.classList.toggle('hide', !this.recent.length);\n\n categories.unshift('Emoji.Recent');\n categories.map(category => {\n const div = divs[category];\n \n if(!div) {\n console.error('no div by category:', category);\n }\n \n emojiScroll.container.append(div);\n this.stickyIntersector.observeStickyHeaderChanges(div);\n return div;\n });\n });\n\n this.content.addEventListener('click', this.onContentClick);\n this.stickyIntersector = EmoticonsDropdown.menuOnClick(menu, emojiScroll);\n this.init = null;\n }\n\n private appendEmoji(emoji: string, container: HTMLElement, prepend = false/* , unified = false */) {\n //const emoji = details.unified;\n //const emoji = (details.unified as string).split('-')\n //.reduce((prev, curr) => prev + String.fromCodePoint(parseInt(curr, 16)), '');\n\n const spanEmoji = document.createElement('span');\n spanEmoji.classList.add('category-item');\n\n let kek: string;\n /* if(unified) {\n kek = RichTextProcessor.wrapRichText('_', {\n entities: [{\n _: 'messageEntityEmoji',\n offset: 0,\n length: emoji.split('-').length,\n unicode: emoji\n }]\n });\n } else { */\n kek = RichTextProcessor.wrapEmojiText(emoji);\n //}\n\n /* if(!kek.includes('emoji')) {\n console.log(emoji, kek, spanEmoji, emoji.length, new TextEncoder().encode(emoji), emojiUnicode(emoji));\n return;\n } */\n \n //console.log(kek);\n \n spanEmoji.innerHTML = kek;\n\n if(spanEmoji.children.length > 1) {\n const first = spanEmoji.firstElementChild;\n spanEmoji.innerHTML = '';\n spanEmoji.append(first);\n }\n\n if(spanEmoji.firstElementChild && !RichTextProcessor.emojiSupported) {\n const image = spanEmoji.firstElementChild as HTMLImageElement;\n image.setAttribute('loading', 'lazy');\n\n const url = image.src;\n if(!this.loadedURLs.has(url)) {\n const placeholder = document.createElement('span');\n placeholder.classList.add('emoji-placeholder');\n \n if(rootScope.settings.animationsEnabled) {\n image.style.opacity = '0';\n placeholder.style.opacity = '1';\n }\n \n image.addEventListener('load', () => {\n fastRaf(() => {\n if(rootScope.settings.animationsEnabled) {\n image.style.opacity = '';\n placeholder.style.opacity = '';\n }\n \n spanEmoji.classList.remove('empty');\n \n this.loadedURLs.add(url);\n });\n }, {once: true});\n \n spanEmoji.append(placeholder);\n }\n }\n \n //spanEmoji = spanEmoji.firstElementChild as HTMLSpanElement;\n //spanEmoji.setAttribute('emoji', emoji);\n if(prepend) container.prepend(spanEmoji);\n else container.appendChild(spanEmoji);\n }\n\n private getEmojiFromElement(element: HTMLElement) {\n if(element.nodeType === 3) return element.nodeValue;\n if(element.tagName === 'SPAN' && !element.classList.contains('emoji')) {\n element = element.firstElementChild as HTMLElement;\n }\n \n return element.getAttribute('alt') || element.innerText;\n }\n\n onContentClick = (e: MouseEvent) => {\n let target = e.target as HTMLElement;\n //if(target.tagName !== 'SPAN') return;\n\n if(target.tagName === 'SPAN' && !target.classList.contains('emoji')) {\n target = findUpClassName(target, 'category-item');\n if(!target) {\n return;\n }\n\n target = target.firstChild as HTMLElement;\n } else if(target.tagName === 'DIV') return;\n\n //console.log('contentEmoji div', target);\n appImManager.chat.input.messageInput.innerHTML += RichTextProcessor.emojiSupported ? \n (target.nodeType === 3 ? target.nodeValue : target.innerHTML) : \n target.outerHTML;\n\n // Recent\n const emoji = this.getEmojiFromElement(target);\n (Array.from(this.recentItemsDiv.children) as HTMLElement[]).forEach((el, idx) => {\n const _emoji = this.getEmojiFromElement(el);\n if(emoji === _emoji) {\n el.remove();\n }\n });\n const scrollHeight = this.recentItemsDiv.scrollHeight;\n this.appendEmoji(emoji, this.recentItemsDiv, true);\n\n this.recent.findAndSplice(e => e === emoji);\n this.recent.unshift(emoji);\n if(this.recent.length > 36) {\n this.recent.length = 36;\n }\n\n this.recentItemsDiv.parentElement.classList.toggle('hide', !this.recent.length);\n\n appStateManager.pushToState('recentEmoji', this.recent);\n\n // Append to input\n const event = new Event('input', {bubbles: true, cancelable: true});\n appImManager.chat.input.messageInput.dispatchEvent(event);\n };\n\n onClose() {\n\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { calcImageInBox } from \"../helpers/dom\";\nimport appDocsManager, {MyDocument} from \"../lib/appManagers/appDocsManager\";\nimport { wrapVideo } from \"./wrappers\";\nimport { LazyLoadQueueRepeat2 } from \"./lazyLoadQueue\";\nimport animationIntersector from \"./animationIntersector\";\nimport Scrollable from \"./scrollable\";\nimport { CancellablePromise, deferredPromise } from \"../helpers/cancellablePromise\";\nimport renderImageFromUrl from \"../helpers/dom/renderImageFromUrl\";\n\nconst width = 400;\nconst maxSingleWidth = width - 100;\nconst height = 100;\n\nexport default class GifsMasonry {\n public lazyLoadQueue: LazyLoadQueueRepeat2;\n private scrollPromise: CancellablePromise<void> = Promise.resolve();\n\n constructor(private element: HTMLElement, private group: string, private scrollable: Scrollable) {\n this.lazyLoadQueue = new LazyLoadQueueRepeat2(undefined, (target, visible) => {\n if(visible) {\n this.processVisibleDiv(target);\n } else {\n this.processInvisibleDiv(target);\n }\n });\n\n /* setInterval(() => {\n // @ts-ignore\n const players = animationIntersector.byGroups[group];\n\n if(players) {\n console.log(`GIFS RENDERED IN ${group}:`, players.length, players.filter(p => !p.animation.paused).length, this.lazyLoadQueue.intersector.getVisible().length);\n }\n }, .25e3); */\n\n let timeout = 0;\n // memory leak\n scrollable.container.addEventListener('scroll', () => {\n if(timeout) {\n clearTimeout(timeout);\n } else {\n this.scrollPromise = deferredPromise<void>();\n //animationIntersector.checkAnimations(true, group);\n }\n\n timeout = window.setTimeout(() => {\n timeout = 0;\n this.scrollPromise.resolve();\n //animationIntersector.checkAnimations(false, group);\n }, 150);\n });\n }\n\n processVisibleDiv = (div: HTMLElement) => {\n const video = div.querySelector('video');\n if(video) {\n return;\n }\n\n //console.log('processVisibleDiv');\n\n const load = () => {\n const docId = div.dataset.docId;\n const doc = appDocsManager.getDoc(docId);\n\n const promise = this.scrollPromise.then(() => {\n const res = wrapVideo({\n doc,\n container: div as HTMLDivElement,\n lazyLoadQueue: null,\n //lazyLoadQueue: EmoticonsDropdown.lazyLoadQueue,\n group: this.group,\n noInfo: true,\n });\n \n const promise = res.loadPromise;\n promise.finally(() => {\n const video = div.querySelector('video');\n\n div.style.opacity = '';\n const img = div.querySelector('img');\n img && img.classList.add('hide');\n\n if(video && !video.parentElement) {\n setTimeout(() => {\n video.src = '';\n video.load();\n const animations = animationIntersector.getAnimations(video);\n animations.forEach(item => {\n animationIntersector.checkAnimation(item, true, true);\n });\n }, 0);\n }\n\n //clearTimeout(timeout);\n if(!this.lazyLoadQueue.intersector.isVisible(div)) {\n this.processInvisibleDiv(div);\n }\n });\n\n return promise;\n });\n\n /* let timeout = window.setTimeout(() => {\n console.error('processVisibleDiv timeout', div, doc);\n }, 1e3); */\n\n return promise;\n };\n\n //return load();\n \n this.lazyLoadQueue.push({div, load});\n };\n\n processInvisibleDiv = async(div: HTMLElement) => {\n return this.scrollPromise.then(async() => {\n //return;\n\n if(this.lazyLoadQueue.intersector.isVisible(div)) {\n return;\n }\n\n const video = div.querySelector('video');\n const img = div.querySelector('img');\n \n if(img) {\n img && img.classList.remove('hide');\n \n await new Promise((resolve) => {\n window.requestAnimationFrame(() => window.requestAnimationFrame(resolve));\n });\n }\n\n if(this.lazyLoadQueue.intersector.isVisible(div)) {\n return;\n }\n \n if(video) {\n video.remove();\n video.src = '';\n video.load();\n const animations = animationIntersector.getAnimations(video);\n animations.forEach(item => {\n animationIntersector.checkAnimation(item, true, true);\n });\n }\n });\n };\n\n public add(doc: MyDocument) {\n let gifWidth = doc.w;\n let gifHeight = doc.h;\n if(gifHeight < height) {\n gifWidth = height / gifHeight * gifWidth;\n gifHeight = height;\n }\n\n const willUseWidth = Math.min(maxSingleWidth, width, gifWidth);\n const {w, h} = calcImageInBox(gifWidth, gifHeight, willUseWidth, height);\n\n /* wastedWidth += w;\n\n if(wastedWidth === width || h < height) {\n wastedWidth = 0;\n console.log('completed line', i, line);\n line = [];\n continue;\n }\n\n line.push(gif); */\n\n //console.log('gif:', gif, w, h);\n\n const div = document.createElement('div');\n div.classList.add('gif', 'fade-in-transition');\n div.style.width = w + 'px';\n div.style.opacity = '0';\n //div.style.height = h + 'px';\n div.dataset.docId = doc.id;\n\n this.element.append(div);\n\n //this.lazyLoadQueue.observe({div, load: this.processVisibleDiv});\n this.lazyLoadQueue.observe(div);\n\n //let preloader = new ProgressivePreloader(div);\n\n const gotThumb = appDocsManager.getThumb(doc, false);\n\n const willBeAPoster = !!gotThumb;\n let img: HTMLImageElement;\n if(willBeAPoster) {\n img = new Image();\n\n if(!gotThumb.thumb.url) {\n gotThumb.promise.then(() => {\n img.src = gotThumb.thumb.url;\n });\n }\n }\n\n const afterRender = () => {\n if(img) {\n div.append(img);\n div.style.opacity = '';\n }\n };\n\n (gotThumb?.thumb?.url ? renderImageFromUrl(img, gotThumb.thumb.url, afterRender) : afterRender());\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport emoticonsDropdown, { EmoticonsDropdown, EmoticonsTab, EMOTICONSSTICKERGROUP } from \"..\";\nimport GifsMasonry from \"../../gifsMasonry\";\nimport Scrollable from \"../../scrollable\";\nimport { putPreloader } from \"../../misc\";\nimport apiManager from \"../../../lib/mtproto/mtprotoworker\";\nimport appDocsManager, {MyDocument} from \"../../../lib/appManagers/appDocsManager\";\n\nexport default class GifsTab implements EmoticonsTab {\n public content: HTMLElement;\n\n init() {\n this.content = document.getElementById('content-gifs');\n const gifsContainer = this.content.firstElementChild as HTMLDivElement;\n gifsContainer.addEventListener('click', EmoticonsDropdown.onMediaClick);\n\n const scroll = new Scrollable(this.content, 'GIFS');\n const masonry = new GifsMasonry(gifsContainer, EMOTICONSSTICKERGROUP, scroll);\n const preloader = putPreloader(this.content, true);\n\n apiManager.invokeApi('messages.getSavedGifs', {hash: 0}).then((res) => {\n //console.log('getSavedGifs res:', res);\n\n if(res._ === 'messages.savedGifs') {\n res.gifs.forEach((doc, idx) => {\n res.gifs[idx] = doc = appDocsManager.saveDoc(doc);\n //if(doc._ === 'documentEmpty') return;\n masonry.add(doc as MyDocument);\n });\n }\n\n preloader.remove();\n });\n\n emoticonsDropdown.addLazyLoadQueueRepeat(masonry.lazyLoadQueue, masonry.processInvisibleDiv);\n\n this.init = null;\n }\n\n onClose() {\n\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport emoticonsDropdown, { EmoticonsDropdown, EMOTICONSSTICKERGROUP, EmoticonsTab } from \"..\";\nimport { readBlobAsText } from \"../../../helpers/blob\";\nimport renderImageFromUrl from \"../../../helpers/dom/renderImageFromUrl\";\nimport mediaSizes from \"../../../helpers/mediaSizes\";\nimport { MessagesAllStickers, StickerSet } from \"../../../layer\";\nimport appDocsManager, { MyDocument } from \"../../../lib/appManagers/appDocsManager\";\nimport appDownloadManager from \"../../../lib/appManagers/appDownloadManager\";\nimport appStickersManager from \"../../../lib/appManagers/appStickersManager\";\nimport lottieLoader from \"../../../lib/lottieLoader\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport rootScope from \"../../../lib/rootScope\";\nimport animationIntersector from \"../../animationIntersector\";\nimport LazyLoadQueue, { LazyLoadQueueRepeat } from \"../../lazyLoadQueue\";\nimport { putPreloader } from \"../../misc\";\nimport Scrollable, { ScrollableX } from \"../../scrollable\";\nimport StickyIntersector from \"../../stickyIntersector\";\nimport { wrapSticker } from \"../../wrappers\";\n\nexport class SuperStickerRenderer {\n lazyLoadQueue: LazyLoadQueueRepeat;\n animatedDivs: Set<HTMLDivElement> = new Set();\n\n constructor(private regularLazyLoadQueue: LazyLoadQueue, private group: string) {\n this.lazyLoadQueue = new LazyLoadQueueRepeat(undefined, (target, visible) => {\n if(!visible) {\n this.processInvisibleDiv(target as HTMLDivElement);\n }\n });\n }\n\n renderSticker(doc: MyDocument, div?: HTMLDivElement, loadPromises?: Promise<any>[]) {\n if(!div) {\n div = document.createElement('div');\n div.classList.add('grid-item', 'super-sticker');\n\n if(doc.sticker === 2) {\n this.animatedDivs.add(div);\n\n this.lazyLoadQueue.observe({\n div, \n load: this.processVisibleDiv\n });\n }\n }\n\n // * This will wrap only a thumb\n wrapSticker({\n doc, \n div,\n lazyLoadQueue: this.regularLazyLoadQueue, \n group: this.group, \n onlyThumb: doc.sticker === 2,\n loadPromises\n });\n\n return div;\n }\n\n checkAnimationContainer = (div: HTMLElement, visible: boolean) => {\n //console.error('checkAnimationContainer', div, visible);\n const players = animationIntersector.getAnimations(div);\n players.forEach(player => {\n if(!visible) {\n animationIntersector.checkAnimation(player, true, true);\n } else {\n animationIntersector.checkAnimation(player, false);\n }\n });\n };\n\n processVisibleDiv = (div: HTMLElement) => {\n const docId = div.dataset.docId;\n const doc = appDocsManager.getDoc(docId);\n \n const size = mediaSizes.active.esgSticker.width;\n\n //console.log('processVisibleDiv:', div);\n\n const promise = wrapSticker({\n doc, \n div: div as HTMLDivElement,\n width: size,\n height: size,\n lazyLoadQueue: null, \n group: this.group, \n onlyThumb: false,\n play: true,\n loop: true\n });\n\n promise.then(() => {\n //clearTimeout(timeout);\n this.checkAnimationContainer(div, this.lazyLoadQueue.intersector.isVisible(div));\n });\n\n /* let timeout = window.setTimeout(() => {\n console.error('processVisibleDiv timeout', div, doc);\n }, 1e3); */\n\n return promise;\n };\n\n processInvisibleDiv = (div: HTMLElement) => {\n const docId = div.dataset.docId;\n const doc = appDocsManager.getDoc(docId);\n\n //console.log('STICKER INvisible:', /* div, */docId);\n\n this.checkAnimationContainer(div, false);\n\n div.innerHTML = '';\n this.renderSticker(doc, div as HTMLDivElement);\n };\n}\n\nexport default class StickersTab implements EmoticonsTab {\n public content: HTMLElement;\n private stickersDiv: HTMLElement;\n\n private stickerSets: {[id: string]: {\n stickers: HTMLElement,\n tab: HTMLElement\n }} = {};\n\n private recentDiv: HTMLElement;\n private recentStickers: MyDocument[] = [];\n\n private scroll: Scrollable;\n\n private menu: HTMLElement;\n \n private mounted = false;\n\n private queueCategoryPush: {element: HTMLElement, prepend: boolean}[] = [];\n\n private stickyIntersector: StickyIntersector;\n\n private superStickerRenderer: SuperStickerRenderer;\n\n categoryPush(categoryDiv: HTMLElement, categoryTitle: string, promise: Promise<MyDocument[]>, prepend?: boolean) {\n //if((docs.length % 5) !== 0) categoryDiv.classList.add('not-full');\n\n const itemsDiv = document.createElement('div');\n itemsDiv.classList.add('category-items', 'super-stickers');\n\n const titleDiv = document.createElement('div');\n titleDiv.classList.add('category-title');\n titleDiv.innerHTML = categoryTitle;\n\n categoryDiv.append(titleDiv, itemsDiv);\n\n this.stickyIntersector.observeStickyHeaderChanges(categoryDiv);\n\n this.queueCategoryPush.push({element: categoryDiv, prepend});\n\n promise.then(documents => {\n documents.forEach(doc => {\n //if(doc._ === 'documentEmpty') return;\n itemsDiv.append(this.superStickerRenderer.renderSticker(doc));\n });\n\n if(this.queueCategoryPush.length) {\n this.queueCategoryPush.forEach(({element, prepend}) => {\n if(prepend) {\n if(this.recentDiv.parentElement) {\n this.stickersDiv.prepend(element);\n this.stickersDiv.prepend(this.recentDiv);\n } else {\n this.stickersDiv.prepend(element);\n }\n } else this.stickersDiv.append(element);\n });\n\n this.queueCategoryPush.length = 0;\n }\n });\n }\n\n async renderStickerSet(set: StickerSet.stickerSet, prepend = false) {\n const categoryDiv = document.createElement('div');\n categoryDiv.classList.add('sticker-category');\n\n const button = document.createElement('button');\n button.classList.add('btn-icon', 'menu-horizontal-div-item');\n\n this.stickerSets[set.id] = {\n stickers: categoryDiv,\n tab: button\n };\n\n if(prepend) {\n this.menu.insertBefore(button, this.menu.firstElementChild.nextSibling);\n } else {\n this.menu.append(button);\n }\n\n //stickersScroll.append(categoryDiv);\n\n const promise = appStickersManager.getStickerSet(set);\n this.categoryPush(categoryDiv, RichTextProcessor.wrapEmojiText(set.title), promise.then(stickerSet => stickerSet.documents as MyDocument[]), prepend);\n const stickerSet = await promise;\n\n //console.log('got stickerSet', stickerSet, li);\n \n if(stickerSet.set.thumbs?.length) {\n EmoticonsDropdown.lazyLoadQueue.push({\n div: button,\n load: () => {\n const downloadOptions = appStickersManager.getStickerSetThumbDownloadOptions(stickerSet.set);\n const promise = appDownloadManager.download(downloadOptions);\n\n if(stickerSet.set.pFlags.animated) {\n return promise\n .then(readBlobAsText)\n //.then(JSON.parse)\n .then(json => {\n lottieLoader.loadAnimationWorker({\n container: button,\n loop: true,\n autoplay: false,\n animationData: json,\n width: 32,\n height: 32,\n needUpscale: true\n }, EMOTICONSSTICKERGROUP);\n });\n } else {\n const image = new Image();\n \n return promise.then(blob => {\n renderImageFromUrl(image, URL.createObjectURL(blob), () => {\n button.append(image);\n });\n });\n }\n }\n });\n } else if(stickerSet.documents[0]._ !== 'documentEmpty') { // as thumb will be used first sticker\n wrapSticker({\n doc: stickerSet.documents[0],\n div: button as any, \n group: EMOTICONSSTICKERGROUP,\n lazyLoadQueue: EmoticonsDropdown.lazyLoadQueue\n }); // kostil\n }\n }\n\n init() {\n this.content = document.getElementById('content-stickers');\n //let stickersDiv = contentStickersDiv.querySelector('.os-content') as HTMLDivElement;\n\n this.recentDiv = document.createElement('div');\n this.recentDiv.classList.add('sticker-category');\n\n let menuWrapper = this.content.previousElementSibling as HTMLDivElement;\n this.menu = menuWrapper.firstElementChild as HTMLUListElement;\n\n let menuScroll = new ScrollableX(menuWrapper);\n\n this.stickersDiv = document.createElement('div');\n this.stickersDiv.classList.add('stickers-categories');\n this.content.append(this.stickersDiv);\n\n /* stickersDiv.addEventListener('mouseover', (e) => {\n let target = e.target as HTMLElement;\n\n if(target.tagName === 'CANVAS') { // turn on sticker\n let animation = lottieLoader.getAnimation(target.parentElement, EMOTICONSSTICKERGROUP);\n\n if(animation) {\n // @ts-ignore\n if(animation.currentFrame === animation.totalFrames - 1) {\n animation.goToAndPlay(0, true);\n } else {\n animation.play();\n }\n }\n }\n }); */\n\n rootScope.on('stickers_installed', (e) => {\n const set: StickerSet.stickerSet = e;\n \n if(!this.stickerSets[set.id] && this.mounted) {\n this.renderStickerSet(set, true);\n }\n });\n\n rootScope.on('stickers_deleted', (e) => {\n const set: StickerSet.stickerSet = e;\n \n if(this.stickerSets[set.id] && this.mounted) {\n const elements = this.stickerSets[set.id];\n elements.stickers.remove();\n elements.tab.remove();\n delete this.stickerSets[set.id];\n }\n });\n\n this.stickersDiv.addEventListener('click', EmoticonsDropdown.onMediaClick);\n\n this.scroll = new Scrollable(this.content, 'STICKERS');\n this.scroll.setVirtualContainer(this.stickersDiv);\n\n this.stickyIntersector = EmoticonsDropdown.menuOnClick(this.menu, this.scroll, menuScroll);\n\n const preloader = putPreloader(this.content, true);\n\n Promise.all([\n appStickersManager.getRecentStickers().then(stickers => {\n this.recentStickers = stickers.stickers.slice(0, 20) as MyDocument[];\n \n //stickersScroll.prepend(categoryDiv);\n\n this.stickerSets['recent'] = {\n stickers: this.recentDiv,\n tab: this.menu.firstElementChild as HTMLElement\n };\n\n preloader.remove();\n this.categoryPush(this.recentDiv, 'Recent', Promise.resolve(this.recentStickers), true);\n }),\n\n appStickersManager.getAllStickers().then((res) => {\n preloader.remove();\n\n for(let set of (res as MessagesAllStickers.messagesAllStickers).sets) {\n this.renderStickerSet(set);\n }\n })\n ]).finally(() => {\n this.mounted = true;\n });\n\n this.superStickerRenderer = new SuperStickerRenderer(EmoticonsDropdown.lazyLoadQueue, EMOTICONSSTICKERGROUP);\n\n emoticonsDropdown.addLazyLoadQueueRepeat(this.superStickerRenderer.lazyLoadQueue, this.superStickerRenderer.processInvisibleDiv);\n\n /* setInterval(() => {\n // @ts-ignore\n const players = Object.values(lottieLoader.players).filter(p => p.width === 80);\n \n console.log('STICKERS RENDERED IN PANEL:', players.length, players.filter(p => !p.paused).length, this.superStickerRenderer.lazyLoadQueue.intersector.getVisible().length);\n }, .25e3); */\n \n\n this.init = null;\n }\n\n pushRecentSticker(doc: MyDocument) {\n if(!this.recentDiv?.parentElement) {\n return;\n }\n\n let div = this.recentDiv.querySelector(`[data-doc-id=\"${doc.id}\"]`);\n if(!div) {\n div = this.superStickerRenderer.renderSticker(doc);\n }\n\n const items = this.recentDiv.querySelector('.category-items');\n items.prepend(div);\n\n if(items.childElementCount > 20) {\n (Array.from(items.children) as HTMLElement[]).slice(20).forEach(el => el.remove());\n }\n }\n\n onClose() {\n\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n * \n * Originally from:\n * https://github.com/zhukov/webogram\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\n * https://github.com/zhukov/webogram/blob/master/LICENSE\n */\n\nimport { toast } from \"../../components/toast\";\nimport { BotInlineResult } from \"../../layer\";\nimport appPeersManager from \"./appPeersManager\";\nimport apiManagerProxy from \"../mtproto/mtprotoworker\";\nimport { RichTextProcessor } from \"../richtextprocessor\";\nimport appDocsManager from \"./appDocsManager\";\nimport appPhotosManager from \"./appPhotosManager\";\nimport appUsersManager from \"./appUsersManager\";\nimport appMessagesManager from \"./appMessagesManager\";\n\nexport class AppInlineBotsManager {\n private inlineResults: {[qId: string]: BotInlineResult} = {};\n\n public getInlineResults(peerId: number, botId: number, query = '', offset = '', geo?: any) {\n return apiManagerProxy.invokeApi('messages.getInlineBotResults', {\n bot: appUsersManager.getUserInput(botId),\n peer: appPeersManager.getInputPeerById(peerId),\n query: query,\n geo_point: (geo && {_: 'inputGeoPoint', lat: geo['lat'], long: geo['long']}) || undefined,\n offset\n }, {/* timeout: 1, */stopTime: -1, noErrorBox: true}).then(botResults => {\n const queryId = botResults.query_id;\n /* delete botResults._;\n delete botResults.query_id; */\n \n /* if(botResults.switch_pm) {\n botResults.switch_pm.rText = RichTextProcessor.wrapRichText(botResults.switch_pm.text, {noLinebreaks: true, noLinks: true});\n } */\n \n botResults.results.forEach(result => {\n const qId = queryId + '_' + result.id;\n /* result.qID = qID;\n result.botID = botID;\n \n result.rTitle = RichTextProcessor.wrapRichText(result.title, {noLinebreaks: true, noLinks: true});\n result.rDescription = RichTextProcessor.wrapRichText(result.description, {noLinebreaks: true, noLinks: true});\n result.initials = ((result as botInlineResult).url || result.title || result.type || '').substr(0, 1); */\n\n if(result._ === 'botInlineMediaResult') {\n if(result.document) {\n result.document = appDocsManager.saveDoc(result.document);\n }\n \n if(result.photo) {\n result.photo = appPhotosManager.savePhoto(result.photo);\n }\n }\n \n this.inlineResults[qId] = result;\n });\n\n return botResults;\n });\n }\n \n /* function getPopularBots () {\n return Storage.get('inline_bots_popular').then(function (bots) {\n var result = []\n var i, len\n var userId\n if (bots && bots.length) {\n var now = tsNow(true)\n for (i = 0, len = bots.length; i < len; i++) {\n if ((now - bots[i][3]) > 14 * 86400) {\n continue\n }\n userId = bots[i][0]\n if (!AppUsersManager.hasUser(userId)) {\n AppUsersManager.saveApiUser(bots[i][1])\n }\n result.push({id: userId, rate: bots[i][2], date: bots[i][3]})\n }\n }\n return result\n })\n }\n \n function pushPopularBot (id) {\n getPopularBots().then(function (bots) {\n var exists = false\n var count = bots.length\n var result = []\n for (var i = 0; i < count; i++) {\n if (bots[i].id === id) {\n exists = true\n bots[i].rate++\n bots[i].date = tsNow(true)\n }\n var user = AppUsersManager.getUser(bots[i].id)\n result.push([bots[i].id, user, bots[i].rate, bots[i].date])\n }\n if (exists) {\n result.sort(function (a, b) {\n return b[2] - a[2]\n })\n } else {\n if (result.length > 15) {\n result = result.slice(0, 15)\n }\n result.push([id, AppUsersManager.getUser(id), 1, tsNow(true)])\n }\n ConfigStorage.set({inline_bots_popular: result})\n \n rootScope.$broadcast('inline_bots_popular')\n })\n }\n \n function resolveInlineMention (username) {\n return AppPeersManager.resolveUsername(username).then(function (peerId) {\n if (peerId > 0) {\n var bot = AppUsersManager.getUser(peerId)\n if (bot.pFlags.bot && bot.bot_inline_placeholder !== undefined) {\n var resolvedBot = {\n username: username,\n id: peerId,\n placeholder: bot.bot_inline_placeholder\n }\n if (bot.pFlags.bot_inline_geo &&\n GeoLocationManager.isAvailable()) {\n return checkGeoLocationAccess(peerId).then(function () {\n return GeoLocationManager.getPosition().then(function (coords) {\n resolvedBot.geo = coords\n return qSync.when(resolvedBot)\n })\n })['catch'](function () {\n return qSync.when(resolvedBot)\n })\n }\n return qSync.when(resolvedBot)\n }\n }\n return $q.reject()\n }, function (error) {\n error.handled = true\n return $q.reject(error)\n })\n }\n \n function regroupWrappedResults (results, rowW, rowH) {\n if (!results ||\n !results[0] ||\n ['photo', 'gif', 'sticker'].indexOf(results[0].type) === -1) {\n return\n }\n var ratios = []\n angular.forEach(results, function (result) {\n var w\n var h, doc\n var photo\n if (result._ === 'botInlineMediaResult') {\n if (doc = result.document) {\n w = result.document.w\n h = result.document.h\n }\n else if (photo = result.photo) {\n var photoSize = (photo.sizes || [])[0]\n w = photoSize && photoSize.w\n h = photoSize && photoSize.h\n }\n }else {\n w = result.w\n h = result.h\n }\n if (!w || !h) {\n w = h = 1\n }\n ratios.push(w / h)\n })\n \n var rows = []\n var curCnt = 0\n var curW = 0\n angular.forEach(ratios, function (ratio) {\n var w = ratio * rowH\n curW += w\n if (!curCnt || curCnt < 4 && curW < (rowW * 1.1)) {\n curCnt++\n } else {\n rows.push(curCnt)\n curCnt = 1\n curW = w\n }\n })\n if (curCnt) {\n rows.push(curCnt)\n }\n \n var i = 0\n var thumbs = []\n var lastRowI = rows.length - 1\n angular.forEach(rows, function (rowCnt, rowI) {\n var lastRow = rowI === lastRowI\n var curRatios = ratios.slice(i, i + rowCnt)\n var sumRatios = 0\n angular.forEach(curRatios, function (ratio) {\n sumRatios += ratio\n })\n angular.forEach(curRatios, function (ratio, j) {\n var thumbH = rowH\n var thumbW = rowW * ratio / sumRatios\n var realW = thumbH * ratio\n if (lastRow && thumbW > realW) {\n thumbW = realW\n }\n var result = results[i + j]\n result.thumbW = Math.floor(thumbW) - 2\n result.thumbH = Math.floor(thumbH) - 2\n })\n \n i += rowCnt\n })\n }\n \n function switchToPM (fromPeerID, botID, startParam) {\n var peerString = AppPeersManager.getPeerString(fromPeerID)\n var setHash = {}\n setHash['inline_switch_pm' + botID] = {peer: peerString, time: tsNow()}\n Storage.set(setHash)\n rootScope.$broadcast('history_focus', {peerString: AppPeersManager.getPeerString(botID)})\n AppMessagesManager.startBot(botID, 0, startParam)\n }\n \n function checkSwitchReturn (botID) {\n var bot = AppUsersManager.getUser(botID)\n if (!bot || !bot.pFlags.bot || !bot.bot_inline_placeholder) {\n return qSync.when(false)\n }\n var key = 'inline_switch_pm' + botID\n return Storage.get(key).then(function (peerData) {\n if (peerData) {\n Storage.remove(key)\n if (tsNow() - peerData.time < 3600000) {\n return peerData.peer\n }\n }\n return false\n })\n }\n \n function switchInlineQuery (botID, toPeerString, query) {\n rootScope.$broadcast('history_focus', {\n peerString: toPeerString,\n attachment: {\n _: 'inline_query',\n mention: '@' + AppUsersManager.getUser(botID).username,\n query: query\n }\n })\n }\n \n function switchInlineButtonClick (id, button) {\n var message = AppMessagesManager.getMessage(id)\n var botID = message.viaBotId || message.fromId\n if (button.pFlags && button.pFlags.same_peer) {\n var peerId = AppMessagesManager.getMessagePeer(message)\n var toPeerString = AppPeersManager.getPeerString(peerId)\n switchInlineQuery(botID, toPeerString, button.query)\n return\n }\n return checkSwitchReturn(botID).then(function (retPeerString) {\n if (retPeerString) {\n return switchInlineQuery(botID, retPeerString, button.query)\n }\n PeersSelectService.selectPeer({\n canSend: true\n }).then(function (toPeerString) {\n return switchInlineQuery(botID, toPeerString, button.query)\n })\n })\n } */\n \n public callbackButtonClick(peerId: number, mid: number, button: any) {\n return apiManagerProxy.invokeApi('messages.getBotCallbackAnswer', {\n peer: appPeersManager.getInputPeerById(peerId),\n msg_id: appMessagesManager.getServerMessageId(mid),\n data: button.data\n }, {timeout: 1, stopTime: -1, noErrorBox: true}).then((callbackAnswer) => {\n if(typeof callbackAnswer.message === 'string' && callbackAnswer.message.length) {\n toast(RichTextProcessor.wrapRichText(callbackAnswer.message, {noLinks: true, noLinebreaks: true}));\n }\n \n //console.log('callbackButtonClick callbackAnswer:', callbackAnswer);\n });\n }\n \n /* function gameButtonClick (id) {\n var message = AppMessagesManager.getMessage(id)\n var peerId = AppMessagesManager.getMessagePeer(message)\n \n return MtpApiManager.invokeApi('messages.getBotCallbackAnswer', {\n peer: AppPeersManager.getInputPeerByID(peerId),\n msg_id: AppMessagesIDsManager.getMessageLocalID(id)\n }, {timeout: 1, stopTime: -1, noErrorBox: true}).then(function (callbackAnswer) {\n if (typeof callbackAnswer.message === 'string' &&\n callbackAnswer.message.length) {\n showCallbackMessage(callbackAnswer.message, callbackAnswer.pFlags.alert)\n }\n else if (typeof callbackAnswer.url === 'string') {\n AppGamesManager.openGame(message.media.game.id, id, callbackAnswer.url)\n }\n })\n }\n\n function sendInlineResult (peerId, qID, options) {\n var inlineResult = inlineResults[qID]\n if (inlineResult === undefined) {\n return false\n }\n pushPopularBot(inlineResult.botID)\n var splitted = qID.split('_')\n var queryID = splitted.shift()\n var resultID = splitted.join('_')\n options = options || {}\n options.viaBotId = inlineResult.botID\n options.queryID = queryID\n options.resultID = resultID\n if (inlineResult.send_message.reply_markup) {\n options.reply_markup = inlineResult.send_message.reply_markup\n }\n \n if (inlineResult.send_message._ === 'botInlineMessageText') {\n options.entities = inlineResult.send_message.entities\n AppMessagesManager.sendText(peerId, inlineResult.send_message.message, options)\n } else {\n var caption = ''\n var inputMedia = false\n switch (inlineResult.send_message._) {\n case 'botInlineMessageMediaAuto':\n caption = inlineResult.send_message.caption\n if (inlineResult._ === 'botInlineMediaResult') {\n var doc = inlineResult.document\n var photo = inlineResult.photo\n if (doc) {\n inputMedia = {\n _: 'inputMediaDocument',\n id: {_: 'inputDocument', id: doc.id, access_hash: doc.access_hash},\n caption: caption\n }\n } else {\n inputMedia = {\n _: 'inputMediaPhoto',\n id: {_: 'inputPhoto', id: photo.id, access_hash: photo.access_hash},\n caption: caption\n }\n }\n }\n break\n \n case 'botInlineMessageMediaGeo':\n inputMedia = {\n _: 'inputMediaGeoPoint',\n geo_point: {\n _: 'inputGeoPoint',\n 'lat': inlineResult.send_message.geo['lat'],\n 'long': inlineResult.send_message.geo['long']\n }\n }\n break\n \n case 'botInlineMessageMediaVenue':\n inputMedia = {\n _: 'inputMediaVenue',\n geo_point: {\n _: 'inputGeoPoint',\n 'lat': inlineResult.send_message.geo['lat'],\n 'long': inlineResult.send_message.geo['long']\n },\n title: inlineResult.send_message.title,\n address: inlineResult.send_message.address,\n provider: inlineResult.send_message.provider,\n venue_id: inlineResult.send_message.venue_id\n }\n break\n \n case 'botInlineMessageMediaContact':\n inputMedia = {\n _: 'inputMediaContact',\n phone_number: inlineResult.send_message.phone_number,\n first_name: inlineResult.send_message.first_name,\n last_name: inlineResult.send_message.last_name\n }\n break\n }\n if (!inputMedia) {\n inputMedia = {\n _: 'messageMediaPending',\n type: inlineResult.type,\n file_name: inlineResult.title || inlineResult.content_url || inlineResult.url,\n size: 0,\n progress: {percent: 30, total: 0}\n }\n }\n AppMessagesManager.sendOther(peerId, inputMedia, options)\n }\n }\n \n function checkGeoLocationAccess (botID) {\n var key = 'bot_access_geo' + botID\n return Storage.get(key).then(function (geoAccess) {\n if (geoAccess && geoAccess.granted) {\n return true\n }\n return ErrorService.confirm({\n type: 'BOT_ACCESS_GEO_INLINE'\n }).then(function () {\n var setHash = {}\n setHash[key] = {granted: true, time: tsNow()}\n Storage.set(setHash)\n return true\n }, function () {\n var setHash = {}\n setHash[key] = {denied: true, time: tsNow()}\n Storage.set(setHash)\n return $q.reject()\n })\n })\n } */\n}\n\nconst appInlineBotsManager = new AppInlineBotsManager();\nexport default appInlineBotsManager;","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport InputSearch from \"../../inputSearch\";\nimport animationIntersector from \"../../animationIntersector\";\nimport appSidebarRight from \"..\";\nimport appUsersManager from \"../../../lib/appManagers/appUsersManager\";\nimport appInlineBotsManager, { AppInlineBotsManager } from \"../../../lib/appManagers/appInlineBotsManager\";\nimport GifsMasonry from \"../../gifsMasonry\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport type { MyDocument } from \"../../../lib/appManagers/appDocsManager\";\nimport mediaSizes from \"../../../helpers/mediaSizes\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\n\nconst ANIMATIONGROUP = 'GIFS-SEARCH';\n\nexport default class AppGifsTab extends SliderSuperTab {\n private inputSearch: InputSearch;\n private gifsDiv: HTMLDivElement;\n\n private nextOffset = '';\n private loadedAll = false;\n\n private gifBotPeerId: number;\n private masonry: GifsMasonry;\n\n private searchPromise: ReturnType<AppInlineBotsManager['getInlineResults']>;\n\n protected init() {\n this.container.id = 'search-gifs-container';\n \n this.inputSearch = new InputSearch('SearchGifsTitle', (value) => {\n this.reset();\n this.search(value);\n });\n \n this.title.replaceWith(this.inputSearch.container);\n \n this.gifsDiv = document.createElement('div');\n this.gifsDiv.classList.add('gifs-masonry');\n attachClickEvent(this.gifsDiv, this.onGifsClick, {listenerSetter: this.listenerSetter});\n \n this.scrollable.append(this.gifsDiv);\n \n this.masonry = new GifsMasonry(this.gifsDiv, ANIMATIONGROUP, this.scrollable);\n //this.backBtn.parentElement.append(this.inputSearch.container);\n }\n\n private onGifsClick = (e: MouseEvent | TouchEvent) => {\n const target = findUpClassName(e.target, 'gif');\n if(!target) return;\n\n const fileId = target.dataset.docId;\n if(appImManager.chat.input.sendMessageWithDocument(fileId)) {\n if(mediaSizes.isMobile) {\n appSidebarRight.onCloseBtnClick();\n }\n } else {\n console.warn('got no doc by id:', fileId);\n }\n };\n\n public onClose() {\n this.scrollable.onScrolledBottom = () => {};\n }\n\n public onCloseAfterTimeout() {\n this.reset();\n this.gifsDiv.innerHTML = '';\n animationIntersector.checkAnimations(undefined, ANIMATIONGROUP);\n this.inputSearch.remove();\n return super.onCloseAfterTimeout();\n }\n\n private reset() {\n this.searchPromise = null;\n this.nextOffset = '';\n this.loadedAll = false;\n this.masonry.lazyLoadQueue.clear();\n }\n\n public open() {\n const ret = super.open();\n appSidebarRight.toggleSidebar(true).then(() => {\n this.search('', true);\n\n this.scrollable.onScrolledBottom = () => {\n this.search(this.inputSearch.value, false);\n };\n });\n return ret;\n }\n\n public async search(query: string, newSearch = true) {\n if(this.searchPromise || this.loadedAll) return;\n\n if(!this.gifBotPeerId) {\n this.gifBotPeerId = (await appUsersManager.resolveUsername('gif')).id;\n }\n\n try {\n this.searchPromise = appInlineBotsManager.getInlineResults(0, this.gifBotPeerId, query, this.nextOffset);\n const { results, next_offset } = await this.searchPromise;\n\n if(this.inputSearch.value !== query) {\n return;\n }\n\n this.searchPromise = null;\n this.nextOffset = next_offset;\n if(newSearch) {\n this.gifsDiv.innerHTML = '';\n }\n\n if(results.length) {\n results.forEach((result) => {\n if(result._ === 'botInlineMediaResult' && result.document) {\n this.masonry.add(result.document as MyDocument);\n }\n });\n } else {\n this.loadedAll = true;\n }\n\n this.scrollable.onScroll();\n } catch(err) {\n this.searchPromise = null;\n console.error('gifs loading error:', err);\n throw err;\n }\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { SliderSuperTab } from \"../../slider\";\nimport InputSearch from \"../../inputSearch\";\nimport LazyLoadQueue from \"../../lazyLoadQueue\";\nimport { attachClickEvent } from \"../../../helpers/dom\";\nimport appImManager from \"../../../lib/appManagers/appImManager\";\nimport appStickersManager from \"../../../lib/appManagers/appStickersManager\";\nimport PopupStickers from \"../../popups/stickers\";\nimport animationIntersector from \"../../animationIntersector\";\nimport { RichTextProcessor } from \"../../../lib/richtextprocessor\";\nimport { wrapSticker } from \"../../wrappers\";\nimport appSidebarRight from \"..\";\nimport { StickerSet, StickerSetCovered } from \"../../../layer\";\nimport { forEachReverse } from \"../../../helpers/array\";\nimport { i18n } from \"../../../lib/langPack\";\nimport findUpClassName from \"../../../helpers/dom/findUpClassName\";\n\nexport default class AppStickersTab extends SliderSuperTab {\n private inputSearch: InputSearch;\n private setsDiv: HTMLDivElement;\n private lazyLoadQueue: LazyLoadQueue;\n\n protected init() {\n this.container.id = 'stickers-container';\n this.container.classList.add('chatlist-container');\n\n this.lazyLoadQueue = new LazyLoadQueue();\n\n this.inputSearch = new InputSearch('StickersTab.SearchPlaceholder', (value) => {\n this.search(value);\n });\n\n this.title.replaceWith(this.inputSearch.container);\n\n this.setsDiv = document.createElement('div');\n this.setsDiv.classList.add('sticker-sets');\n this.scrollable.append(this.setsDiv);\n\n attachClickEvent(this.setsDiv, (e) => {\n const sticker = findUpClassName(e.target, 'sticker-set-sticker');\n if(sticker) {\n const docId = sticker.dataset.docId;\n appImManager.chat.input.sendMessageWithDocument(docId);\n return;\n }\n\n const target = findUpClassName(e.target, 'sticker-set');\n if(!target) return;\n\n const id = target.dataset.stickerSet as string;\n const access_hash = target.dataset.access_hash as string;\n\n const button = findUpClassName(e.target, 'sticker-set-button') as HTMLElement;\n if(button) {\n e.preventDefault();\n e.cancelBubble = true;\n\n button.setAttribute('disabled', 'true');\n \n appStickersManager.getStickerSet({id, access_hash}).then(full => {\n appStickersManager.toggleStickerSet(full.set).then(changed => {\n if(changed) {\n button.textContent = '';\n button.append(i18n(full.set.installed_date ? 'Stickers.SearchAdded' : 'Stickers.SearchAdd'));\n button.classList.toggle('gray', !!full.set.installed_date);\n }\n }).finally(() => {\n //button.style.width = set.installed_date ? '68px' : '52px';\n button.removeAttribute('disabled');\n });\n });\n } else {\n appStickersManager.getStickerSet({id, access_hash}).then(full => {\n new PopupStickers(full.set).show();\n });\n }\n }, {listenerSetter: this.listenerSetter});\n }\n\n public onCloseAfterTimeout() {\n this.setsDiv.innerHTML = '';\n animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');\n return super.onCloseAfterTimeout();\n }\n\n public renderSet(set: StickerSet.stickerSet) {\n //console.log('renderSet:', set);\n const div = document.createElement('div');\n div.classList.add('sticker-set');\n\n const header = document.createElement('div');\n header.classList.add('sticker-set-header');\n\n const details = document.createElement('div');\n details.classList.add('sticker-set-details');\n details.innerHTML = `\n <div class=\"sticker-set-name\">${RichTextProcessor.wrapEmojiText(set.title)}</div>\n `;\n\n const countDiv = document.createElement('div');\n countDiv.classList.add('sticker-set-count');\n countDiv.append(i18n('Stickers', [set.count]));\n details.append(countDiv);\n \n const button = document.createElement('button');\n button.classList.add('btn-primary', 'btn-color-primary', 'sticker-set-button');\n button.append(i18n(set.installed_date ? 'Stickers.SearchAdded' : 'Stickers.SearchAdd'));\n // button.style.width = set.installed_date ? '68px' : '52px';\n\n if(set.installed_date) {\n button.classList.add('gray');\n }\n\n //ripple(button);\n\n header.append(details, button);\n\n const stickersDiv = document.createElement('div');\n stickersDiv.classList.add('sticker-set-stickers');\n\n const count = Math.min(5, set.count);\n for(let i = 0; i < count; ++i) {\n const stickerDiv = document.createElement('div');\n stickerDiv.classList.add('sticker-set-sticker');\n\n stickersDiv.append(stickerDiv);\n }\n\n appStickersManager.getStickerSet(set).then(set => {\n //console.log('renderSet got set:', set);\n \n for(let i = 0; i < count; ++i) {\n const div = stickersDiv.children[i] as HTMLDivElement;\n const doc = set.documents[i];\n if(doc._ === 'documentEmpty') {\n continue;\n }\n\n wrapSticker({\n doc, \n div, \n lazyLoadQueue: this.lazyLoadQueue, \n group: 'STICKERS-SEARCH', \n /* play: false,\n loop: false, */\n play: true,\n loop: true,\n width: 68,\n height: 68\n });\n }\n });\n\n /* const onMouseOver = () => {\n const animations: AnimationItem['animation'][] = [];\n for(let i = 0; i < count; ++i) {\n const stickerDiv = stickersDiv.children[i] as HTMLElement;\n const animationItem = animationIntersector.getAnimation(stickerDiv);\n if(!animationItem) continue;\n\n const animation = animationItem.animation;\n\n animations.push(animation);\n animation.loop = true;\n animation.play();\n }\n\n div.addEventListener('mouseout', () => {\n animations.forEach(animation => {\n animation.loop = false;\n });\n\n div.addEventListener('mouseover', onMouseOver, {once: true});\n }, {once: true});\n };\n\n div.addEventListener('mouseover', onMouseOver, {once: true}); */\n\n div.dataset.stickerSet = set.id;\n div.dataset.access_hash = set.access_hash;\n div.dataset.title = set.title;\n\n div.append(header, stickersDiv);\n\n this.setsDiv.append(div);\n }\n\n public open() {\n const ret = super.open();\n appSidebarRight.toggleSidebar(true).then(() => {\n this.renderFeatured();\n });\n\n return ret;\n }\n\n public renderFeatured() {\n return appStickersManager.getFeaturedStickers().then(coveredSets => {\n if(this.inputSearch.value) {\n return;\n }\n\n coveredSets = this.filterRendered('', coveredSets);\n coveredSets.forEach(set => {\n this.renderSet(set.set);\n });\n });\n }\n\n private filterRendered(query: string, coveredSets: StickerSetCovered[]) {\n coveredSets = coveredSets.slice();\n\n const children = Array.from(this.setsDiv.children) as HTMLElement[];\n forEachReverse(children, el => {\n const id = el.dataset.stickerSet;\n const index = coveredSets.findIndex(covered => covered.set.id === id);\n \n if(index !== -1) {\n coveredSets.splice(index, 1);\n } else if(!query || !el.dataset.title.toLowerCase().includes(query.toLowerCase())) {\n el.remove();\n }\n });\n\n animationIntersector.checkAnimations(undefined, 'STICKERS-SEARCH');\n\n return coveredSets;\n }\n\n public search(query: string) {\n if(!query) {\n return this.renderFeatured();\n }\n\n return appStickersManager.searchStickerSets(query, false).then(coveredSets => {\n if(this.inputSearch.value !== query) {\n return;\n }\n\n //console.log('search result:', coveredSets);\n\n coveredSets = this.filterRendered(query, coveredSets);\n coveredSets.forEach(set => {\n this.renderSet(set.set);\n });\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport appChatsManager from \"../../lib/appManagers/appChatsManager\";\nimport appImManager from \"../../lib/appManagers/appImManager\";\nimport rootScope from \"../../lib/rootScope\";\nimport { attachClickEvent, blurActiveElement, whichChild } from \"../../helpers/dom\";\nimport animationIntersector from \"../animationIntersector\";\nimport { horizontalMenu } from \"../horizontalMenu\";\nimport LazyLoadQueue, { LazyLoadQueueIntersector } from \"../lazyLoadQueue\";\nimport Scrollable, { ScrollableX } from \"../scrollable\";\nimport appSidebarRight from \"../sidebarRight\";\nimport StickyIntersector from \"../stickyIntersector\";\nimport EmojiTab from \"./tabs/emoji\";\nimport GifsTab from \"./tabs/gifs\";\nimport StickersTab from \"./tabs/stickers\";\nimport { pause } from \"../../helpers/schedulers\";\nimport { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport AppGifsTab from \"../sidebarRight/tabs/gifs\";\nimport AppStickersTab from \"../sidebarRight/tabs/stickers\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\n\nexport const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';\n\nexport interface EmoticonsTab {\n init: () => void,\n onCloseAfterTimeout?: () => void\n}\n\nconst KEEP_OPEN = false;\nconst TOGGLE_TIMEOUT = 200;\nconst ANIMATION_DURATION = 200;\n\nexport class EmoticonsDropdown {\n public static lazyLoadQueue = new LazyLoadQueue();\n private element: HTMLElement;\n\n public emojiTab: EmojiTab;\n public stickersTab: StickersTab;\n public gifsTab: GifsTab;\n\n private container: HTMLElement;\n private tabsEl: HTMLElement;\n private tabId = -1;\n\n private tabs: {[id: number]: EmoticonsTab};\n\n public searchButton: HTMLElement;\n public deleteBtn: HTMLElement;\n \n private displayTimeout: number;\n\n public events: {\n onClose: Array<() => void>,\n onCloseAfter: Array<() => void>,\n onOpen: Array<() => void>,\n onOpenAfter: Array<() => void>\n } = {\n onClose: [],\n onCloseAfter: [],\n onOpen: [],\n onOpenAfter: []\n };\n\n private selectTab: ReturnType<typeof horizontalMenu>;\n private forceClose = false;\n\n constructor() {\n this.element = document.getElementById('emoji-dropdown') as HTMLDivElement;\n }\n\n public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) {\n let firstTime = true;\n if(isTouchSupported) {\n attachClickEvent(button, () => {\n if(firstTime) {\n firstTime = false;\n this.toggle(true);\n } else {\n this.toggle();\n }\n }, {listenerSetter});\n } else {\n listenerSetter.add(button, 'mouseover', (e) => {\n //console.log('onmouseover button');\n if(firstTime) {\n listenerSetter.add(button, 'mouseout', this.onMouseOut);\n firstTime = false;\n }\n\n clearTimeout(this.displayTimeout);\n this.displayTimeout = window.setTimeout(() => {\n this.toggle(true);\n }, TOGGLE_TIMEOUT);\n });\n }\n }\n\n private onMouseOut = (e: MouseEvent) => {\n if(KEEP_OPEN) return;\n clearTimeout(this.displayTimeout);\n if(!this.element.classList.contains('active')) return;\n\n const toElement = (e as any).toElement as Element;\n if(toElement && findUpClassName(toElement, 'emoji-dropdown')) {\n return;\n }\n\n this.displayTimeout = window.setTimeout(() => {\n this.toggle(false);\n }, TOGGLE_TIMEOUT);\n };\n\n private init() {\n this.emojiTab = new EmojiTab();\n this.stickersTab = new StickersTab();\n this.gifsTab = new GifsTab();\n\n this.tabs = {\n 0: this.emojiTab,\n 1: this.stickersTab,\n 2: this.gifsTab\n };\n\n this.container = this.element.querySelector('.emoji-container .tabs-container') as HTMLDivElement;\n this.tabsEl = this.element.querySelector('.emoji-tabs') as HTMLUListElement;\n this.selectTab = horizontalMenu(this.tabsEl, this.container, this.onSelectTabClick, () => {\n const tab = this.tabs[this.tabId];\n if(tab.init) {\n tab.init();\n }\n\n tab.onCloseAfterTimeout && tab.onCloseAfterTimeout();\n animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP);\n });\n\n this.searchButton = this.element.querySelector('.emoji-tabs-search');\n this.searchButton.addEventListener('click', () => {\n if(this.tabId === 1) {\n if(!appSidebarRight.isTabExists(AppStickersTab)) {\n new AppStickersTab(appSidebarRight).open();\n }\n } else {\n if(!appSidebarRight.isTabExists(AppGifsTab)) {\n new AppGifsTab(appSidebarRight).open();\n }\n }\n });\n\n this.deleteBtn = this.element.querySelector('.emoji-tabs-delete');\n this.deleteBtn.addEventListener('click', () => {\n const input = appImManager.chat.input.messageInput;\n if((input.lastChild as any)?.tagName) {\n input.lastElementChild.remove();\n } else if(input.lastChild) {\n if(!input.lastChild.textContent.length) {\n input.lastChild.remove();\n } else {\n input.lastChild.textContent = input.lastChild.textContent.slice(0, -1);\n }\n }\n\n const event = new Event('input', {bubbles: true, cancelable: true});\n appImManager.chat.input.messageInput.dispatchEvent(event);\n //appSidebarRight.stickersTab.init();\n });\n\n (this.tabsEl.children[1] as HTMLLIElement).click(); // set emoji tab\n if(this.tabs[0].init) {\n this.tabs[0].init(); // onTransitionEnd не вызовется, т.к. это первая открытая вкладка\n }\n\n rootScope.on('peer_changed', this.checkRights);\n this.checkRights();\n\n if(!isTouchSupported) {\n this.element.onmouseout = this.onMouseOut;\n this.element.onmouseover = (e) => {\n if(this.forceClose) {\n return;\n }\n\n //console.log('onmouseover element');\n clearTimeout(this.displayTimeout);\n };\n }\n }\n\n private onSelectTabClick = (id: number) => {\n if(this.tabId === id) {\n return;\n }\n \n animationIntersector.checkAnimations(true, EMOTICONSSTICKERGROUP);\n\n this.tabId = id;\n this.searchButton.classList.toggle('hide', this.tabId === 0);\n this.deleteBtn.classList.toggle('hide', this.tabId !== 0);\n };\n\n public checkRights = () => {\n const peerId = appImManager.chat.peerId;\n const children = this.tabsEl.children;\n const tabsElements = Array.from(children) as HTMLElement[];\n\n const canSendStickers = peerId > 0 || appChatsManager.hasRights(peerId, 'send_stickers');\n tabsElements[2].toggleAttribute('disabled', !canSendStickers);\n\n const canSendGifs = peerId > 0 || appChatsManager.hasRights(peerId, 'send_gifs');\n tabsElements[3].toggleAttribute('disabled', !canSendGifs);\n\n const active = this.tabsEl.querySelector('.active');\n if(active && whichChild(active) !== 1 && (!canSendStickers || !canSendGifs)) {\n this.selectTab(0, false);\n }\n };\n\n public toggle = async(enable?: boolean) => {\n //if(!this.element) return;\n const willBeActive = (!!this.element.style.display && enable === undefined) || enable;\n if(this.init) {\n if(willBeActive) {\n this.init();\n this.init = null;\n } else {\n return;\n }\n }\n\n if(isTouchSupported) {\n if(willBeActive) {\n //appImManager.chat.input.saveScroll();\n if(blurActiveElement()) {\n await pause(100);\n }\n }\n }\n\n if(this.element.parentElement !== appImManager.chat.input.chatInput) {\n appImManager.chat.input.chatInput.append(this.element);\n }\n \n if((this.element.style.display && enable === undefined) || enable) {\n this.events.onOpen.forEach(cb => cb());\n\n EmoticonsDropdown.lazyLoadQueue.lock();\n //EmoticonsDropdown.lazyLoadQueue.unlock();\n animationIntersector.lockIntersectionGroup(EMOTICONSSTICKERGROUP);\n\n this.element.style.display = '';\n void this.element.offsetLeft; // reflow\n this.element.classList.add('active');\n\n clearTimeout(this.displayTimeout);\n this.displayTimeout = window.setTimeout(() => {\n animationIntersector.unlockIntersectionGroup(EMOTICONSSTICKERGROUP);\n EmoticonsDropdown.lazyLoadQueue.unlock();\n EmoticonsDropdown.lazyLoadQueue.refresh();\n\n this.forceClose = false;\n this.container.classList.remove('disable-hover');\n\n this.events.onOpenAfter.forEach(cb => cb());\n }, isTouchSupported ? 0 : ANIMATION_DURATION);\n\n // ! can't use together with resizeObserver\n /* if(isTouchSupported) {\n const height = this.element.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;\n console.log('[ESG]: toggle: enable height', height);\n appImManager.chat.bubbles.scrollable.scrollTop += height;\n } */\n\n /* if(touchSupport) {\n this.restoreScroll();\n } */\n } else {\n this.events.onClose.forEach(cb => cb());\n\n EmoticonsDropdown.lazyLoadQueue.lock();\n //EmoticonsDropdown.lazyLoadQueue.lock();\n\n // нужно залочить группу и выключить стикеры\n animationIntersector.lockIntersectionGroup(EMOTICONSSTICKERGROUP);\n animationIntersector.checkAnimations(true, EMOTICONSSTICKERGROUP);\n\n this.element.classList.remove('active');\n\n clearTimeout(this.displayTimeout);\n this.displayTimeout = window.setTimeout(() => {\n this.element.style.display = 'none';\n\n // теперь можно убрать visible, чтобы они не включились после фокуса\n animationIntersector.unlockIntersectionGroup(EMOTICONSSTICKERGROUP);\n EmoticonsDropdown.lazyLoadQueue.unlock();\n EmoticonsDropdown.lazyLoadQueue.refresh();\n\n this.forceClose = false;\n this.container.classList.remove('disable-hover');\n\n this.events.onCloseAfter.forEach(cb => cb());\n }, isTouchSupported ? 0 : ANIMATION_DURATION);\n\n /* if(isTouchSupported) {\n const scrollHeight = this.container.scrollHeight;\n if(scrollHeight) {\n const height = this.container.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;\n appImManager.chat.bubbles.scrollable.scrollTop -= height;\n }\n } */\n\n /* if(touchSupport) {\n this.restoreScroll();\n } */\n }\n\n //animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP);\n };\n\n public static menuOnClick = (menu: HTMLElement, scroll: Scrollable, menuScroll?: ScrollableX) => {\n let prevId = 0;\n let jumpedTo = -1;\n\n const setActive = (id: number) => {\n if(id === prevId) {\n return false;\n }\n\n menu.children[prevId].classList.remove('active');\n menu.children[id].classList.add('active');\n prevId = id;\n\n return true;\n };\n\n const stickyIntersector = new StickyIntersector(scroll.container, (stuck, target) => {\n //console.log('sticky scrollTOp', stuck, target, scroll.container.scrollTop);\n\n if(Math.abs(jumpedTo - scroll.container.scrollTop) <= 1) {\n return;\n } else {\n jumpedTo = -1;\n }\n\n const which = whichChild(target);\n if(!stuck && which) { // * due to stickyIntersector\n return;\n }\n\n setActive(which);\n\n if(menuScroll) {\n if(which < menu.childElementCount - 4) {\n menuScroll.container.scrollLeft = (which - 3) * 47;\n } else {\n menuScroll.container.scrollLeft = which * 47;\n }\n }\n });\n\n menu.addEventListener('click', (e) => {\n let target = e.target as HTMLElement;\n target = findUpClassName(target, 'menu-horizontal-div-item');\n\n if(!target) {\n return;\n }\n\n const which = whichChild(target);\n\n /* if(menuScroll) {\n menuScroll.scrollIntoView(target, false, 0);\n } */\n\n if(!setActive(which)) {\n return;\n }\n\n const element = (scroll.splitUp || scroll.container).children[which] as HTMLElement;\n const offsetTop = element.offsetTop + 1; // * due to stickyIntersector\n\n scroll.container.scrollTop = jumpedTo = offsetTop;\n\n //console.log('set scrollTop:', offsetTop);\n });\n\n return stickyIntersector;\n };\n\n public static onMediaClick = (e: MouseEvent, clearDraft = false) => {\n let target = e.target as HTMLElement;\n target = findUpTag(target, 'DIV');\n\n if(!target) return;\n \n const fileId = target.dataset.docId;\n if(!fileId) return;\n\n if(appImManager.chat.input.sendMessageWithDocument(fileId, undefined, clearDraft)) {\n /* dropdown.classList.remove('active');\n toggleEl.classList.remove('active'); */\n emoticonsDropdown.forceClose = true;\n emoticonsDropdown.container.classList.add('disable-hover');\n emoticonsDropdown.toggle(false);\n } else {\n console.warn('got no doc by id:', fileId);\n }\n };\n\n public addLazyLoadQueueRepeat(lazyLoadQueue: LazyLoadQueueIntersector, processInvisibleDiv: (div: HTMLElement) => void) {\n this.events.onClose.push(() => {\n lazyLoadQueue.lock();\n });\n\n this.events.onCloseAfter.push(() => {\n const divs = lazyLoadQueue.intersector.getVisible();\n\n for(const div of divs) {\n processInvisibleDiv(div);\n }\n\n lazyLoadQueue.intersector.clearVisible();\n });\n\n this.events.onOpenAfter.push(() => {\n lazyLoadQueue.unlockAndRefresh();\n });\n }\n}\n\nconst emoticonsDropdown = new EmoticonsDropdown();\nMOUNT_CLASS_TO.emoticonsDropdown = emoticonsDropdown;\nexport default emoticonsDropdown;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { cancelEvent } from \"../../helpers/dom\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\nimport rootScope from \"../../lib/rootScope\";\nimport ButtonMenu, { ButtonMenuItemOptions } from \"../buttonMenu\";\nimport { attachContextMenuListener, openBtnMenu } from \"../misc\";\n\nexport default class SendMenu {\n public sendMenu: HTMLDivElement;\n private sendMenuButtons: (ButtonMenuItemOptions & {verify: () => boolean})[];\n private type: 'schedule' | 'reminder';\n \n constructor(options: {\n onSilentClick: () => void,\n onScheduleClick: () => void,\n listenerSetter?: ListenerSetter,\n openSide: string,\n onContextElement: HTMLElement,\n onOpen?: () => boolean\n }) {\n this.sendMenuButtons = [{\n icon: 'mute',\n text: 'Chat.Send.WithoutSound',\n onClick: options.onSilentClick,\n verify: () => this.type === 'schedule'\n }, {\n icon: 'schedule',\n text: 'Chat.Send.ScheduledMessage',\n onClick: options.onScheduleClick,\n verify: () => this.type === 'schedule'\n }, {\n icon: 'schedule',\n text: 'Chat.Send.SetReminder',\n onClick: options.onScheduleClick,\n verify: () => this.type === 'reminder'\n }];\n \n this.sendMenu = ButtonMenu(this.sendMenuButtons, options.listenerSetter);\n this.sendMenu.classList.add('menu-send', options.openSide);\n\n attachContextMenuListener(options.onContextElement, (e: any) => {\n if(options.onOpen && !options.onOpen()) {\n return;\n }\n\n this.sendMenuButtons.forEach(button => {\n button.element.classList.toggle('hide', !button.verify());\n });\n \n cancelEvent(e);\n openBtnMenu(this.sendMenu);\n }, options.listenerSetter);\n }\n\n public setPeerId(peerId: number) {\n this.type = peerId === rootScope.myId ? 'reminder' : 'schedule';\n }\n};\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { Poll } from \"../../lib/appManagers/appPollsManager\";\nimport type Chat from \"../chat/chat\";\nimport PopupElement from \".\";\nimport { cancelEvent, getRichValue, isInputEmpty, whichChild } from \"../../helpers/dom\";\nimport CheckboxField from \"../checkboxField\";\nimport InputField from \"../inputField\";\nimport RadioField from \"../radioField\";\nimport Scrollable from \"../scrollable\";\nimport SendContextMenu from \"../chat/sendContextMenu\";\nimport { MessageEntity } from \"../../layer\";\nimport I18n, { _i18n, i18n } from \"../../lib/langPack\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\n\nconst MAX_LENGTH_QUESTION = 255;\nconst MAX_LENGTH_OPTION = 100;\nconst MAX_LENGTH_SOLUTION = 200;\n\nexport default class PopupCreatePoll extends PopupElement {\n private questionInputField: InputField;\n private questions: HTMLElement;\n private scrollable: Scrollable;\n private tempId = 0;\n\n private anonymousCheckboxField: CheckboxField;\n private multipleCheckboxField: PopupCreatePoll['anonymousCheckboxField'];\n private quizCheckboxField: PopupCreatePoll['anonymousCheckboxField'];\n\n private correctAnswers: Uint8Array[];\n private quizSolutionField: InputField;\n private optionInputFields: InputField[];\n\n constructor(private chat: Chat) {\n super('popup-create-poll popup-new-media', null, {closable: true, withConfirm: 'NewPoll.Create', body: true});\n\n _i18n(this.title, 'NewPoll');\n\n this.questionInputField = new InputField({\n placeholder: 'AskAQuestion',\n label: 'AskAQuestion', \n name: 'question', \n maxLength: MAX_LENGTH_QUESTION\n });\n\n this.questionInputField.input.addEventListener('input', () => {\n this.handleChange();\n });\n\n this.optionInputFields = [];\n\n if(this.chat.type !== 'scheduled') {\n const sendMenu = new SendContextMenu({\n onSilentClick: () => {\n this.chat.input.sendSilent = true;\n this.send();\n },\n onScheduleClick: () => {\n this.chat.input.scheduleSending(() => {\n this.send();\n });\n },\n openSide: 'bottom-left',\n onContextElement: this.btnConfirm,\n });\n \n sendMenu.setPeerId(this.chat.peerId);\n\n this.header.append(sendMenu.sendMenu);\n }\n\n this.header.append(this.questionInputField.container);\n\n const hr = document.createElement('hr');\n const d = document.createElement('div');\n d.classList.add('caption');\n _i18n(d, 'PollOptions');\n\n this.questions = document.createElement('form');\n this.questions.classList.add('poll-create-questions');\n\n const dd = document.createElement('div');\n dd.classList.add('poll-create-settings');\n \n const settingsCaption = document.createElement('div');\n settingsCaption.classList.add('caption');\n _i18n(settingsCaption, 'Settings');\n\n if(!this.chat.appPeersManager.isBroadcast(this.chat.peerId)) {\n this.anonymousCheckboxField = new CheckboxField({\n text: 'NewPoll.Anonymous', \n name: 'anonymous'\n });\n this.anonymousCheckboxField.input.checked = true;\n dd.append(this.anonymousCheckboxField.label);\n }\n \n this.multipleCheckboxField = new CheckboxField({\n text: 'NewPoll.MultipleChoice', \n name: 'multiple'\n });\n this.quizCheckboxField = new CheckboxField({\n text: 'NewPoll.Quiz', \n name: 'quiz'\n });\n\n this.multipleCheckboxField.input.addEventListener('change', () => {\n const checked = this.multipleCheckboxField.input.checked;\n this.quizCheckboxField.input.toggleAttribute('disabled', checked);\n });\n\n this.quizCheckboxField.input.addEventListener('change', () => {\n const checked = this.quizCheckboxField.input.checked;\n\n (Array.from(this.questions.children) as HTMLElement[]).map(el => {\n el.classList.toggle('radio-field', checked);\n });\n\n if(!checked) {\n this.correctAnswers = undefined;\n this.quizSolutionField.setValueSilently('');\n }\n\n quizElements.forEach(el => el.classList.toggle('hide', !checked));\n\n this.multipleCheckboxField.input.toggleAttribute('disabled', checked);\n this.handleChange();\n });\n\n dd.append(this.multipleCheckboxField.label, this.quizCheckboxField.label);\n\n const quizElements: HTMLElement[] = [];\n\n const quizSolutionCaption = document.createElement('div');\n quizSolutionCaption.classList.add('caption');\n _i18n(quizSolutionCaption, 'AccDescrQuizExplanation');\n\n const quizHr = document.createElement('hr');\n\n const quizSolutionContainer = document.createElement('div');\n quizSolutionContainer.classList.add('poll-create-questions');\n\n this.quizSolutionField = new InputField({\n placeholder: 'NewPoll.Explanation.Placeholder', \n label: 'NewPoll.Explanation.Placeholder',\n name: 'solution',\n maxLength: MAX_LENGTH_SOLUTION\n });\n\n this.questionInputField.input.addEventListener('input', () => {\n this.handleChange();\n });\n\n const quizSolutionSubtitle = document.createElement('div');\n quizSolutionSubtitle.classList.add('subtitle');\n _i18n(quizSolutionSubtitle, 'AddAnExplanationInfo');\n\n quizSolutionContainer.append(this.quizSolutionField.container, quizSolutionSubtitle);\n\n quizElements.push(quizHr, quizSolutionCaption, quizSolutionContainer);\n quizElements.forEach(el => el.classList.add('hide'));\n\n this.body.parentElement.insertBefore(hr, this.body);\n this.body.append(d, this.questions, document.createElement('hr'), settingsCaption, dd, ...quizElements);\n\n this.btnConfirm.addEventListener('click', this.onSubmitClick);\n\n this.scrollable = new Scrollable(this.body);\n this.appendMoreField();\n\n this.onEscape = () => {\n return !this.getFilledAnswers().length;\n };\n\n this.handleChange();\n }\n\n private getFilledAnswers() {\n const answers = Array.from(this.questions.children).map((el, idx) => {\n const input = el.querySelector('.input-field-input') as HTMLElement;\n return input instanceof HTMLInputElement ? input.value : getRichValue(input);\n }).filter(v => !!v.trim());\n\n return answers;\n }\n\n private onSubmitClick = () => {\n this.send();\n };\n\n private validate() {\n const question = this.questionInputField.value;\n if(!question) {\n return false;\n }\n\n if(question.length > MAX_LENGTH_QUESTION) {\n return false;\n }\n\n if(this.quizCheckboxField.input.checked && !this.correctAnswers?.length) {\n return false;\n }\n\n const answers = this.getFilledAnswers();\n if(answers.length < 2) {\n return false;\n }\n \n const tooLongOption = answers.find(a => a.length > MAX_LENGTH_OPTION);\n if(tooLongOption) {\n return false;\n }\n\n const quizSolutionEntities: MessageEntity[] = [];\n const quizSolution = getRichValue(this.quizSolutionField.input, quizSolutionEntities) || undefined;\n if(quizSolution?.length > MAX_LENGTH_SOLUTION) {\n return false;\n }\n\n return true;\n }\n\n private handleChange() {\n const valid = this.validate();\n this.btnConfirm.toggleAttribute('disabled', !valid);\n }\n\n public send(force = false) {\n const question = this.questionInputField.value;\n\n const answers = this.getFilledAnswers();\n\n const quizSolutionEntities: MessageEntity[] = [];\n const quizSolution = getRichValue(this.quizSolutionField.input, quizSolutionEntities) || undefined;\n\n if(this.chat.type === 'scheduled' && !force) {\n this.chat.input.scheduleSending(() => {\n this.send(true);\n });\n \n return;\n }\n\n this.btnClose.click();\n this.btnConfirm.removeEventListener('click', this.onSubmitClick);\n\n //const randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];\n //const randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString();\n\n const pFlags: Poll['pFlags'] = {};\n\n if(this.anonymousCheckboxField && !this.anonymousCheckboxField.input.checked) {\n pFlags.public_voters = true;\n }\n\n if(this.multipleCheckboxField.input.checked) {\n pFlags.multiple_choice = true;\n }\n\n if(this.quizCheckboxField.input.checked) {\n pFlags.quiz = true;\n }\n\n const poll: Poll = {\n _: 'poll',\n pFlags,\n question,\n answers: answers.map((value, idx) => {\n return {\n _: 'pollAnswer',\n text: value,\n option: new Uint8Array([idx])\n };\n }),\n id: undefined\n };\n //poll.id = randomIDS;\n\n const inputMediaPoll = this.chat.appPollsManager.getInputMediaPoll(poll, this.correctAnswers, quizSolution, quizSolutionEntities);\n\n //console.log('Will try to create poll:', inputMediaPoll);\n\n this.chat.appMessagesManager.sendOther(this.chat.peerId, inputMediaPoll, {\n threadId: this.chat.threadId,\n replyToMsgId: this.chat.input.replyToMsgId,\n scheduleDate: this.chat.input.scheduleDate,\n silent: this.chat.input.sendSilent\n });\n\n if(this.chat.input.helperType === 'reply') {\n this.chat.input.clearHelper();\n }\n\n this.chat.input.onMessageSent(false, false);\n }\n\n onInput = (e: Event) => {\n const target = e.target as HTMLInputElement;\n\n const radioLabel = findUpTag(target, 'LABEL');\n const isEmpty = isInputEmpty(target);\n if(!isEmpty) {\n target.parentElement.classList.add('is-filled');\n radioLabel.classList.remove('hidden-widget');\n radioLabel.firstElementChild.removeAttribute('disabled');\n }\n\n const isLast = !radioLabel.nextElementSibling;\n if(isLast && !isEmpty && this.questions.childElementCount < 10) {\n this.appendMoreField();\n }\n\n this.handleChange();\n };\n\n onDeleteClick = (e: MouseEvent) => {\n const target = e.target as HTMLSpanElement;\n const label = findUpTag(target, 'LABEL');\n const idx = whichChild(label);\n\n if(this.correctAnswers && this.correctAnswers[0][0] === idx) {\n this.correctAnswers = undefined;\n }\n\n label.remove();\n this.optionInputFields.splice(idx, 1);\n\n this.optionInputFields.forEach((inputField, idx) => {\n inputField.options.labelOptions.length = 0;\n inputField.options.labelOptions.push(idx + 1);\n const i18nElement = I18n.weakMap.get(inputField.label.firstElementChild as HTMLElement);\n i18nElement.update();\n });\n\n this.handleChange();\n };\n\n private appendMoreField() {\n const tempId = this.tempId++;\n const idx = this.questions.childElementCount + 1;\n const questionField = new InputField({\n placeholder: 'NewPoll.OptionsAddOption', \n label: 'NewPoll.OptionLabel',\n labelOptions: [idx],\n name: 'question-' + tempId, \n maxLength: MAX_LENGTH_OPTION\n });\n questionField.input.addEventListener('input', this.onInput);\n\n const radioField = new RadioField({\n text: '', \n name: 'question'\n });\n radioField.main.append(questionField.container);\n questionField.input.addEventListener('click', cancelEvent);\n radioField.label.classList.add('hidden-widget');\n radioField.input.disabled = true;\n if(!this.quizCheckboxField.input.checked) {\n radioField.label.classList.remove('radio-field');\n }\n radioField.input.addEventListener('change', () => {\n const checked = radioField.input.checked;\n if(checked) {\n const idx = whichChild(radioField.label);\n this.correctAnswers = [new Uint8Array([idx])];\n this.handleChange();\n }\n });\n\n const deleteBtn = document.createElement('span');\n deleteBtn.classList.add('btn-icon', 'tgico-close');\n questionField.container.append(deleteBtn);\n \n deleteBtn.addEventListener('click', this.onDeleteClick, {once: true});\n\n this.questions.append(radioField.label);\n\n this.scrollable.scrollIntoViewNew(this.questions.lastElementChild as HTMLElement, 'center');\n //this.scrollable.scrollTo(this.scrollable.scrollHeight, 'top', true, true);\n\n this.optionInputFields.push(questionField);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type Chat from \"../chat/chat\";\nimport { calcImageInBox, placeCaretAtEnd, isSendShortcutPressed } from \"../../helpers/dom\";\nimport InputField from \"../inputField\";\nimport PopupElement from \".\";\nimport Scrollable from \"../scrollable\";\nimport { toast } from \"../toast\";\nimport { prepareAlbum, wrapDocument } from \"../wrappers\";\nimport CheckboxField from \"../checkboxField\";\nimport SendContextMenu from \"../chat/sendContextMenu\";\nimport { createPosterFromVideo, onVideoLoad } from \"../../helpers/files\";\nimport { MyDocument } from \"../../lib/appManagers/appDocsManager\";\nimport I18n, { i18n, LangPackKey } from \"../../lib/langPack\";\n\ntype SendFileParams = Partial<{\n file: File,\n objectURL: string,\n thumbBlob: Blob,\n thumbURL: string,\n width: number,\n height: number,\n duration: number\n}>;\n\nconst MAX_LENGTH_CAPTION = 1024;\n\n// TODO: .gif upload as video\n\nexport default class PopupNewMedia extends PopupElement {\n private input: HTMLElement;\n private mediaContainer: HTMLElement;\n private groupCheckboxField: CheckboxField;\n private wasInputValue = '';\n\n private willAttach: Partial<{\n type: 'media' | 'document',\n isMedia: true,\n group: boolean,\n sendFileDetails: SendFileParams[]\n }> = {\n sendFileDetails: [],\n group: false\n };\n inputField: InputField;\n\n constructor(private chat: Chat, files: File[], willAttachType: PopupNewMedia['willAttach']['type']) {\n super('popup-send-photo popup-new-media', null, {closable: true, withConfirm: 'Modal.Send'});\n\n this.willAttach.type = willAttachType;\n\n this.btnConfirm.addEventListener('click', () => this.send());\n\n if(this.chat.type !== 'scheduled') {\n const sendMenu = new SendContextMenu({\n onSilentClick: () => {\n this.chat.input.sendSilent = true;\n this.send();\n },\n onScheduleClick: () => {\n this.chat.input.scheduleSending(() => {\n this.send();\n });\n },\n openSide: 'bottom-left',\n onContextElement: this.btnConfirm,\n });\n\n sendMenu.setPeerId(this.chat.peerId);\n\n this.header.append(sendMenu.sendMenu);\n }\n\n this.mediaContainer = document.createElement('div');\n this.mediaContainer.classList.add('popup-photo');\n const scrollable = new Scrollable(null);\n scrollable.container.append(this.mediaContainer);\n \n this.inputField = new InputField({\n placeholder: 'PreviewSender.CaptionPlaceholder',\n label: 'Caption',\n name: 'photo-caption',\n maxLength: MAX_LENGTH_CAPTION,\n showLengthOn: 80\n });\n this.input = this.inputField.input;\n\n this.inputField.value = this.wasInputValue = this.chat.input.messageInputField.value;\n this.chat.input.messageInputField.value = '';\n\n this.container.append(scrollable.container);\n\n if(files.length > 1) {\n this.groupCheckboxField = new CheckboxField({\n text: 'PreviewSender.GroupItems', \n name: 'group-items'\n });\n this.container.append(this.groupCheckboxField.label, this.inputField.container);\n \n this.groupCheckboxField.input.checked = true;\n this.willAttach.group = true;\n\n this.groupCheckboxField.input.addEventListener('change', () => {\n const checked = this.groupCheckboxField.input.checked;\n \n this.willAttach.group = checked;\n this.willAttach.sendFileDetails.length = 0;\n\n //this.mediaContainer.innerHTML = '';\n //this.container.classList.remove('is-media', 'is-document', 'is-album');\n this.attachFiles(files);\n });\n }\n \n this.container.append(this.inputField.container);\n\n this.attachFiles(files);\n }\n\n private onKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement;\n if(target !== this.input) {\n this.input.focus();\n placeCaretAtEnd(this.input);\n }\n \n if(isSendShortcutPressed(e)) {\n this.btnConfirm.click();\n }\n };\n\n public send(force = false) {\n if(this.chat.type === 'scheduled' && !force) {\n this.chat.input.scheduleSending(() => {\n this.send(true);\n });\n \n return;\n }\n\n let caption = this.inputField.value;\n if(caption.length > MAX_LENGTH_CAPTION) {\n toast(I18n.format('Error.PreviewSender.CaptionTooLong', true));\n return;\n }\n\n this.hide();\n const willAttach = this.willAttach;\n willAttach.isMedia = willAttach.type === 'media' ? true : undefined;\n\n //console.log('will send files with options:', willAttach);\n\n const peerId = this.chat.peerId;\n const input = this.chat.input;\n const silent = input.sendSilent;\n const scheduleDate = input.scheduleDate;\n\n if(willAttach.sendFileDetails.length > 1 && willAttach.group) {\n for(let i = 0; i < willAttach.sendFileDetails.length;) {\n let firstType = willAttach.sendFileDetails[i].file.type.split('/')[0];\n for(var k = 0; k < 10 && i < willAttach.sendFileDetails.length; ++i, ++k) {\n const type = willAttach.sendFileDetails[i].file.type.split('/')[0];\n if(firstType !== type) {\n break;\n }\n }\n\n const w = {...willAttach};\n w.sendFileDetails = willAttach.sendFileDetails.slice(i - k, i);\n\n this.chat.appMessagesManager.sendAlbum(peerId, w.sendFileDetails.map(d => d.file), Object.assign({\n caption,\n replyToMsgId: input.replyToMsgId,\n threadId: this.chat.threadId,\n isMedia: willAttach.isMedia,\n silent,\n scheduleDate,\n clearDraft: true as true\n }, w));\n\n caption = undefined;\n input.replyToMsgId = this.chat.threadId;\n }\n } else {\n if(caption) {\n if(willAttach.sendFileDetails.length > 1) {\n this.chat.appMessagesManager.sendText(peerId, caption, {\n replyToMsgId: input.replyToMsgId, \n threadId: this.chat.threadId,\n silent, \n scheduleDate,\n clearDraft: true\n });\n caption = '';\n //input.replyToMsgId = undefined;\n }\n }\n \n const promises = willAttach.sendFileDetails.map(params => {\n const promise = this.chat.appMessagesManager.sendFile(peerId, params.file, Object.assign({\n //isMedia: willAttach.isMedia, \n isMedia: willAttach.isMedia, \n caption,\n replyToMsgId: input.replyToMsgId,\n threadId: this.chat.threadId,\n silent,\n scheduleDate,\n clearDraft: true as true\n }, params));\n\n caption = '';\n return promise;\n });\n\n input.replyToMsgId = this.chat.threadId;\n }\n\n //Promise.all(promises);\n\n //appMessagesManager.sendFile(appImManager.peerId, willAttach.file, willAttach);\n \n input.onMessageSent();\n }\n\n public attachFile = (file: File) => {\n const willAttach = this.willAttach;\n return new Promise<HTMLDivElement>((resolve) => {\n const params: SendFileParams = {};\n params.file = file;\n //console.log('selected file:', file, typeof(file), willAttach);\n const itemDiv = document.createElement('div');\n switch(willAttach.type) {\n case 'media': {\n const isVideo = file.type.indexOf('video/') === 0;\n\n itemDiv.classList.add('popup-item-media');\n\n if(isVideo) {\n const video = document.createElement('video');\n const source = document.createElement('source');\n source.src = params.objectURL = URL.createObjectURL(file);\n video.autoplay = true;\n video.controls = false;\n video.muted = true;\n video.setAttribute('playsinline', 'true');\n\n video.addEventListener('timeupdate', () => {\n video.pause();\n }, {once: true});\n\n onVideoLoad(video).then(() => {\n params.width = video.videoWidth;\n params.height = video.videoHeight;\n params.duration = Math.floor(video.duration);\n\n itemDiv.append(video);\n createPosterFromVideo(video).then(blob => {\n params.thumbBlob = blob;\n params.thumbURL = URL.createObjectURL(blob);\n resolve(itemDiv);\n });\n });\n\n video.append(source);\n } else {\n const img = new Image();\n img.src = params.objectURL = URL.createObjectURL(file);\n img.onload = () => {\n params.width = img.naturalWidth;\n params.height = img.naturalHeight;\n\n itemDiv.append(img);\n resolve(itemDiv);\n };\n }\n \n break;\n }\n\n case 'document': {\n const isPhoto = file.type.indexOf('image/') !== -1;\n const isAudio = file.type.indexOf('audio/') !== -1;\n if(isPhoto || isAudio) {\n params.objectURL = URL.createObjectURL(file);\n }\n\n const docDiv = wrapDocument({\n message: {\n _: 'message',\n pFlags: {\n is_outgoing: true\n },\n mid: 0,\n peerId: 0,\n media: {\n _: 'messageMediaDocument',\n document: {\n _: 'document',\n file: file,\n file_name: file.name || '',\n size: file.size,\n type: isPhoto ? 'photo' : 'doc',\n url: params.objectURL,\n downloaded: true\n } as MyDocument\n }\n } as any\n });\n\n const finish = () => {\n itemDiv.append(docDiv);\n resolve(itemDiv);\n };\n\n if(isPhoto) {\n const img = new Image();\n img.src = params.objectURL;\n img.onload = () => {\n params.width = img.naturalWidth;\n params.height = img.naturalHeight;\n\n finish();\n };\n\n img.onerror = finish;\n } else {\n finish();\n }\n\n break;\n }\n }\n\n willAttach.sendFileDetails.push(params);\n });\n };\n\n public attachFiles(files: File[]) {\n const container = this.container;\n const willAttach = this.willAttach;\n\n /* if(files.length > 10 && willAttach.type === 'media') {\n willAttach.type = 'document';\n } */\n\n files = files.filter(file => {\n if(willAttach.type === 'media') {\n return ['image/', 'video/'].find(s => file.type.indexOf(s) === 0);\n } else {\n return true;\n }\n });\n\n Promise.all(files.map(this.attachFile)).then(results => {\n this.container.classList.remove('is-media', 'is-document', 'is-album');\n this.mediaContainer.innerHTML = '';\n\n if(files.length) {\n let key: LangPackKey;\n const args: any[] = [];\n if(willAttach.type === 'document') {\n key = 'PreviewSender.SendFile';\n args.push(files.length);\n container.classList.add('is-document');\n } else {\n container.classList.add('is-media');\n \n let foundPhotos = 0;\n let foundVideos = 0;\n files.forEach(file => {\n if(file.type.indexOf('image/') === 0) ++foundPhotos;\n else if(file.type.indexOf('video/') === 0) ++foundVideos;\n });\n \n const sum = foundPhotos + foundVideos;\n if(sum > 1 && willAttach.group) {\n key = 'PreviewSender.SendAlbum';\n const albumsLength = Math.ceil(sum / 10);\n args.push(albumsLength);\n } else if(foundPhotos) {\n key = 'PreviewSender.SendPhoto';\n args.push(foundPhotos);\n } else if(foundVideos) {\n key = 'PreviewSender.SendVideo';\n args.push(foundVideos);\n }\n }\n\n this.title.textContent = '';\n this.title.append(i18n(key, args));\n }\n\n if(willAttach.type === 'media') {\n if(willAttach.sendFileDetails.length > 1 && willAttach.group) {\n container.classList.add('is-album');\n\n for(let i = 0; i < results.length; i += 10) {\n const albumContainer = document.createElement('div');\n albumContainer.classList.add('popup-album');\n\n albumContainer.append(...results.slice(i, i + 10));\n prepareAlbum({\n container: albumContainer,\n items: willAttach.sendFileDetails.slice(i, i + 10).map(o => ({w: o.width, h: o.height})),\n maxWidth: 380,\n minWidth: 100,\n spacing: 4\n });\n\n this.mediaContainer.append(albumContainer);\n }\n\n //console.log('chatInput album layout:', layout);\n } else {\n for(let i = 0; i < results.length; ++i) {\n const params = willAttach.sendFileDetails[i];\n const div = results[i];\n const {w, h} = calcImageInBox(params.width, params.height, 380, 320);\n div.style.width = w + 'px';\n div.style.height = h + 'px';\n this.mediaContainer.append(div);\n }\n }\n } else {\n this.mediaContainer.append(...results);\n }\n\n // show now\n if(!this.element.classList.contains('active')) {\n document.body.addEventListener('keydown', this.onKeyDown);\n this.onClose = () => {\n if(this.wasInputValue) {\n this.chat.input.messageInputField.value = this.wasInputValue;\n }\n\n document.body.removeEventListener('keydown', this.onKeyDown);\n };\n this.show();\n }\n });\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\nimport { MyDocument } from \"../../lib/appManagers/appDocsManager\";\nimport { CHAT_ANIMATION_GROUP } from \"../../lib/appManagers/appImManager\";\nimport appStickersManager from \"../../lib/appManagers/appStickersManager\";\nimport { EmoticonsDropdown } from \"../emoticonsDropdown\";\nimport { SuperStickerRenderer } from \"../emoticonsDropdown/tabs/stickers\";\nimport LazyLoadQueue from \"../lazyLoadQueue\";\nimport Scrollable from \"../scrollable\";\nimport SetTransition from \"../singleTransition\";\n\nexport default class StickersHelper {\n private container: HTMLElement;\n private stickersContainer: HTMLElement;\n private scrollable: Scrollable;\n private superStickerRenderer: SuperStickerRenderer;\n private lazyLoadQueue: LazyLoadQueue;\n private lastEmoticon = '';\n\n constructor(private appendTo: HTMLElement) {\n this.container = document.createElement('div');\n this.container.classList.add('stickers-helper', 'z-depth-1');\n\n this.appendTo.append(this.container);\n }\n\n public checkEmoticon(emoticon: string) {\n if(this.lastEmoticon === emoticon) return;\n\n if(this.lastEmoticon && !emoticon) {\n if(this.container) {\n SetTransition(this.container, 'is-visible', false, 200, () => {\n if(this.stickersContainer) {\n this.stickersContainer.innerHTML = '';\n }\n });\n }\n }\n\n this.lastEmoticon = emoticon;\n if(this.lazyLoadQueue) {\n this.lazyLoadQueue.clear();\n }\n \n if(!emoticon) {\n return;\n }\n\n appStickersManager.getStickersByEmoticon(emoticon)\n .then((stickers) => {\n if(this.lastEmoticon !== emoticon) {\n return;\n }\n\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n const container = this.stickersContainer.cloneNode() as HTMLElement;\n\n let ready: Promise<void>;\n\n this.lazyLoadQueue.clear();\n if(stickers.length) {\n ready = new Promise<void>((resolve) => {\n const promises: Promise<any>[] = [];\n stickers.forEach(sticker => {\n container.append(this.superStickerRenderer.renderSticker(sticker as MyDocument, undefined, promises));\n });\n\n (Promise.all(promises) as Promise<any>).then(resolve, resolve);\n });\n } else {\n ready = Promise.resolve();\n }\n\n ready.then(() => {\n this.stickersContainer.replaceWith(container);\n this.stickersContainer = container;\n\n SetTransition(this.container, 'is-visible', !!stickers.length, 200);\n this.scrollable.scrollTop = 0;\n });\n });\n }\n\n private init() {\n this.container.addEventListener('click', (e) => {\n if(!findUpClassName(e.target, 'super-sticker')) {\n return;\n }\n\n EmoticonsDropdown.onMediaClick(e, true);\n });\n\n this.stickersContainer = document.createElement('div');\n this.stickersContainer.classList.add('stickers-helper-stickers', 'super-stickers');\n\n this.container.append(this.stickersContainer);\n\n this.scrollable = new Scrollable(this.container);\n this.lazyLoadQueue = new LazyLoadQueue();\n this.superStickerRenderer = new SuperStickerRenderer(this.lazyLoadQueue, CHAT_ANIMATION_GROUP);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport PopupDatePicker from \"./datePicker\";\n\nconst getMinDate = () => {\n const date = new Date();\n //date.setDate(date.getDate() - 1);\n date.setHours(0, 0, 0, 0);\n return date;\n};\n\nexport default class PopupSchedule extends PopupDatePicker {\n constructor(initDate: Date, onPick: (timestamp: number) => void) {\n super(initDate, onPick, {\n noButtons: true,\n noTitle: true,\n closable: true,\n withConfirm: true,\n minDate: getMinDate(),\n maxDate: (() => {\n const date = new Date();\n date.setFullYear(date.getFullYear() + 1);\n date.setDate(date.getDate() - 1);\n return date;\n })(),\n withTime: true,\n showOverflowMonths: true\n });\n\n this.element.classList.add('popup-schedule');\n this.header.append(this.controlsDiv);\n this.title.replaceWith(this.monthTitle);\n this.body.append(this.btnConfirm);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppNotificationsManager } from '../../lib/appManagers/appNotificationsManager';\nimport type { AppChatsManager } from '../../lib/appManagers/appChatsManager';\nimport type { AppDocsManager, MyDocument } from \"../../lib/appManagers/appDocsManager\";\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppPeersManager } from '../../lib/appManagers/appPeersManager';\nimport type { AppWebPagesManager } from \"../../lib/appManagers/appWebPagesManager\";\nimport type { AppImManager } from '../../lib/appManagers/appImManager';\nimport type { AppDraftsManager, MyDraftMessage } from '../../lib/appManagers/appDraftsManager';\nimport type { ServerTimeManager } from '../../lib/mtproto/serverTimeManager';\nimport type Chat from './chat';\nimport Recorder from '../../../public/recorder.min';\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport apiManager from \"../../lib/mtproto/mtprotoworker\";\n//import Recorder from '../opus-recorder/dist/recorder.min';\nimport opusDecodeController from \"../../lib/opusDecodeController\";\nimport RichTextProcessor from \"../../lib/richtextprocessor\";\nimport { attachClickEvent, blurActiveElement, cancelEvent, cancelSelection, getRichValue, isInputEmpty, markdownTags, MarkdownType, placeCaretAtEnd, isSendShortcutPressed } from \"../../helpers/dom\";\nimport { ButtonMenuItemOptions } from '../buttonMenu';\nimport emoticonsDropdown from \"../emoticonsDropdown\";\nimport PopupCreatePoll from \"../popups/createPoll\";\nimport PopupForward from '../popups/forward';\nimport PopupNewMedia from '../popups/newMedia';\nimport { toast } from \"../toast\";\nimport { wrapReply } from \"../wrappers\";\nimport InputField from '../inputField';\nimport { MessageEntity, DraftMessage } from '../../layer';\nimport StickersHelper from './stickersHelper';\nimport ButtonIcon from '../buttonIcon';\nimport DivAndCaption from '../divAndCaption';\nimport ButtonMenuToggle from '../buttonMenuToggle';\nimport ListenerSetter from '../../helpers/listenerSetter';\nimport Button from '../button';\nimport PopupSchedule from '../popups/schedule';\nimport SendMenu from './sendContextMenu';\nimport rootScope from '../../lib/rootScope';\nimport PopupPinMessage from '../popups/unpinMessage';\nimport { debounce } from '../../helpers/schedulers';\nimport { tsNow } from '../../helpers/date';\nimport appNavigationController from '../appNavigationController';\nimport { isMobile } from '../../helpers/userAgent';\nimport { i18n } from '../../lib/langPack';\nimport { generateTail } from './bubbles';\nimport findUpClassName from '../../helpers/dom/findUpClassName';\n\nconst RECORD_MIN_TIME = 500;\nconst POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\\'t allowed in this group.';\n\ntype ChatInputHelperType = 'edit' | 'webpage' | 'forward' | 'reply';\n\nexport default class ChatInput {\n public pageEl = document.getElementById('page-chats') as HTMLDivElement;\n public messageInput: HTMLElement;\n public messageInputField: InputField;\n public fileInput: HTMLInputElement;\n public inputMessageContainer: HTMLDivElement;\n public btnSend = document.getElementById('btn-send') as HTMLButtonElement;\n public btnCancelRecord: HTMLButtonElement;\n public lastUrl = '';\n public lastTimeType = 0;\n\n public chatInput: HTMLElement;\n public inputContainer: HTMLElement;\n public rowsWrapper: HTMLDivElement;\n private newMessageWrapper: HTMLDivElement;\n private btnToggleEmoticons: HTMLButtonElement;\n public btnSendContainer: HTMLDivElement;\n\n public attachMenu: HTMLButtonElement;\n private attachMenuButtons: (ButtonMenuItemOptions & {verify: (peerId: number) => boolean})[];\n\n public sendMenu: SendMenu;\n\n public replyElements: {\n container?: HTMLElement,\n cancelBtn?: HTMLButtonElement,\n titleEl?: HTMLElement,\n subtitleEl?: HTMLElement\n } = {};\n\n public willSendWebPage: any = null;\n public forwardingMids: number[] = [];\n public forwardingFromPeerId: number = 0;\n public replyToMsgId: number;\n public editMsgId: number;\n public noWebPage: true;\n public scheduleDate: number;\n public sendSilent: true;\n\n private recorder: any;\n private recording = false;\n private recordCanceled = false;\n private recordTimeEl: HTMLElement;\n private recordRippleEl: HTMLElement;\n private recordStartTime = 0;\n\n // private scrollTop = 0;\n // private scrollOffsetTop = 0;\n // private scrollDiff = 0;\n\n public helperType: Exclude<ChatInputHelperType, 'webpage'>;\n private helperFunc: () => void;\n private helperWaitingForward: boolean;\n\n public willAttachType: 'document' | 'media';\n\n private lockRedo = false;\n private canRedoFromHTML = '';\n readonly undoHistory: string[] = [];\n readonly executedHistory: string[] = [];\n private canUndoFromHTML = '';\n\n public stickersHelper: StickersHelper;\n public listenerSetter: ListenerSetter;\n\n public pinnedControlBtn: HTMLButtonElement;\n\n public goDownBtn: HTMLButtonElement;\n public goDownUnreadBadge: HTMLElement;\n public btnScheduled: HTMLButtonElement;\n\n public saveDraftDebounced: () => void;\n\n public fakeRowsWrapper: HTMLDivElement;\n private fakePinnedControlBtn: HTMLElement;\n\n constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appDocsManager: AppDocsManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private appWebPagesManager: AppWebPagesManager, private appImManager: AppImManager, private appDraftsManager: AppDraftsManager, private serverTimeManager: ServerTimeManager, private appNotificationsManager: AppNotificationsManager) {\n this.listenerSetter = new ListenerSetter();\n }\n\n public construct() {\n this.chatInput = document.createElement('div');\n this.chatInput.classList.add('chat-input');\n this.chatInput.style.display = 'none';\n\n this.inputContainer = document.createElement('div');\n this.inputContainer.classList.add('chat-input-container');\n\n this.rowsWrapper = document.createElement('div');\n this.rowsWrapper.classList.add('rows-wrapper', 'chat-input-wrapper');\n\n const tail = generateTail();\n this.rowsWrapper.append(tail);\n\n const fakeRowsWrapper = this.fakeRowsWrapper = document.createElement('div');\n fakeRowsWrapper.classList.add('fake-wrapper', 'fake-rows-wrapper');\n\n const fakeSelectionWrapper = document.createElement('div');\n fakeSelectionWrapper.classList.add('fake-wrapper', 'fake-selection-wrapper');\n\n this.inputContainer.append(this.rowsWrapper, fakeRowsWrapper, fakeSelectionWrapper);\n this.chatInput.append(this.inputContainer);\n\n this.goDownBtn = Button('bubbles-go-down btn-corner btn-circle z-depth-1 hide', {icon: 'arrow_down'});\n this.inputContainer.append(this.goDownBtn);\n\n attachClickEvent(this.goDownBtn, (e) => {\n cancelEvent(e);\n this.chat.bubbles.onGoDownClick();\n }, {listenerSetter: this.listenerSetter});\n\n // * constructor end\n\n /* let setScrollTopTimeout: number;\n // @ts-ignore\n let height = window.visualViewport.height; */\n // @ts-ignore\n // this.listenerSetter.add(window.visualViewport, 'resize', () => {\n // const scrollable = this.chat.bubbles.scrollable;\n // const wasScrolledDown = scrollable.isScrolledDown;\n \n // /* if(wasScrolledDown) {\n // this.saveScroll();\n // } */\n \n // // @ts-ignore\n // let newHeight = window.visualViewport.height;\n // const diff = height - newHeight;\n // const scrollTop = scrollable.scrollTop;\n // const needScrollTop = wasScrolledDown ? scrollable.scrollHeight : scrollTop + diff; // * wasScrolledDown это проверка для десктоп хрома, когда пропадает панель загрузок снизу\n\n // console.log('resize before', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, wasScrolledDown, scrollable.lastScrollTop, diff, needScrollTop);\n\n // scrollable.scrollTop = needScrollTop;\n\n // if(setScrollTopTimeout) clearTimeout(setScrollTopTimeout);\n // setScrollTopTimeout = window.setTimeout(() => {\n // const diff = height - newHeight;\n // const isScrolledDown = scrollable.scrollHeight - Math.round(scrollable.scrollTop + scrollable.container.offsetHeight + diff) <= 1;\n // height = newHeight;\n\n // scrollable.scrollTop = needScrollTop;\n \n // console.log('resize after', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, scrollable.isScrolledDown, scrollable.lastScrollTop, isScrolledDown);\n\n // /* if(isScrolledDown) {\n // scrollable.scrollTop = scrollable.scrollHeight;\n // } */\n\n // //scrollable.scrollTop += diff;\n // setScrollTopTimeout = 0;\n // }, 0);\n // });\n\n // ! Can't use it with resizeObserver\n /* this.listenerSetter.add(window.visualViewport, 'resize', () => {\n const scrollable = this.chat.bubbles.scrollable;\n const wasScrolledDown = scrollable.isScrolledDown;\n\n // @ts-ignore\n let newHeight = window.visualViewport.height;\n const diff = height - newHeight;\n const needScrollTop = wasScrolledDown ? scrollable.scrollHeight : scrollable.scrollTop + diff; // * wasScrolledDown это проверка для десктоп хрома, когда пропадает панель загрузок снизу\n\n //console.log('resize before', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, wasScrolledDown, scrollable.lastScrollTop, diff, needScrollTop);\n\n scrollable.scrollTop = needScrollTop;\n height = newHeight;\n\n if(setScrollTopTimeout) clearTimeout(setScrollTopTimeout);\n setScrollTopTimeout = window.setTimeout(() => { // * try again for scrolled down Android Chrome\n scrollable.scrollTop = needScrollTop;\n \n //console.log('resize after', scrollable.scrollTop, scrollable.container.clientHeight, scrollable.scrollHeight, scrollable.isScrolledDown, scrollable.lastScrollTop, isScrolledDown);\n setScrollTopTimeout = 0;\n }, 0);\n }); */\n }\n\n public constructPeerHelpers() {\n this.replyElements.container = document.createElement('div');\n this.replyElements.container.classList.add('reply-wrapper');\n\n this.replyElements.cancelBtn = ButtonIcon('close reply-cancel');\n\n const dac = new DivAndCaption('reply');\n\n this.replyElements.titleEl = dac.title;\n this.replyElements.subtitleEl = dac.subtitle;\n\n this.replyElements.container.append(this.replyElements.cancelBtn, dac.container);\n\n this.newMessageWrapper = document.createElement('div');\n this.newMessageWrapper.classList.add('new-message-wrapper');\n\n this.btnToggleEmoticons = ButtonIcon('none toggle-emoticons', {noRipple: true});\n\n this.inputMessageContainer = document.createElement('div');\n this.inputMessageContainer.classList.add('input-message-container');\n\n if(this.chat.type === 'chat') {\n this.goDownUnreadBadge = document.createElement('span');\n this.goDownUnreadBadge.classList.add('badge', 'badge-24', 'badge-primary');\n this.goDownBtn.append(this.goDownUnreadBadge);\n\n this.btnScheduled = ButtonIcon('scheduled', {noRipple: true});\n this.btnScheduled.classList.add('btn-scheduled', 'hide');\n\n attachClickEvent(this.btnScheduled, (e) => {\n this.appImManager.openScheduled(this.chat.peerId);\n }, {listenerSetter: this.listenerSetter});\n\n this.listenerSetter.add(rootScope, 'scheduled_new', (e) => {\n const peerId = e.peerId;\n\n if(this.chat.peerId !== peerId) {\n return;\n }\n\n this.btnScheduled.classList.remove('hide');\n });\n\n this.listenerSetter.add(rootScope, 'scheduled_delete', (e) => {\n const peerId = e.peerId;\n\n if(this.chat.peerId !== peerId) {\n return;\n }\n\n this.appMessagesManager.getScheduledMessages(this.chat.peerId).then(value => {\n this.btnScheduled.classList.toggle('hide', !value.length);\n });\n });\n }\n\n this.attachMenuButtons = [{\n icon: 'image',\n text: 'Chat.Input.Attach.PhotoOrVideo',\n onClick: () => {\n this.fileInput.value = '';\n this.fileInput.setAttribute('accept', 'image/*, video/*');\n this.willAttachType = 'media';\n this.fileInput.click();\n },\n verify: (peerId: number) => peerId > 0 || this.appChatsManager.hasRights(peerId, 'send_media')\n }, {\n icon: 'document',\n text: 'Chat.Input.Attach.Document',\n onClick: () => {\n this.fileInput.value = '';\n this.fileInput.removeAttribute('accept');\n this.willAttachType = 'document';\n this.fileInput.click();\n },\n verify: (peerId: number) => peerId > 0 || this.appChatsManager.hasRights(peerId, 'send_media')\n }, {\n icon: 'poll',\n text: 'Poll',\n onClick: () => {\n new PopupCreatePoll(this.chat).show();\n },\n verify: (peerId: number) => peerId < 0 && this.appChatsManager.hasRights(peerId, 'send_polls')\n }];\n\n this.attachMenu = ButtonMenuToggle({noRipple: true, listenerSetter: this.listenerSetter}, 'top-left', this.attachMenuButtons);\n this.attachMenu.classList.add('attach-file', 'tgico-attach');\n this.attachMenu.classList.remove('tgico-more');\n\n //this.inputContainer.append(this.sendMenu);\n\n this.recordTimeEl = document.createElement('div');\n this.recordTimeEl.classList.add('record-time');\n\n this.fileInput = document.createElement('input');\n this.fileInput.type = 'file';\n this.fileInput.multiple = true;\n this.fileInput.style.display = 'none';\n\n this.newMessageWrapper.append(...[this.btnToggleEmoticons, this.inputMessageContainer, this.btnScheduled, this.attachMenu, this.recordTimeEl, this.fileInput].filter(Boolean));\n\n this.rowsWrapper.append(this.replyElements.container);\n this.stickersHelper = new StickersHelper(this.rowsWrapper);\n this.rowsWrapper.append(this.newMessageWrapper);\n\n this.btnCancelRecord = ButtonIcon('delete danger btn-circle z-depth-1 btn-record-cancel');\n\n this.btnSendContainer = document.createElement('div');\n this.btnSendContainer.classList.add('btn-send-container');\n\n this.recordRippleEl = document.createElement('div');\n this.recordRippleEl.classList.add('record-ripple');\n\n this.btnSend = ButtonIcon('none btn-circle z-depth-1 btn-send animated-button-icon');\n this.btnSend.insertAdjacentHTML('afterbegin', `\n <span class=\"tgico tgico-send\"></span>\n <span class=\"tgico tgico-schedule\"></span>\n <span class=\"tgico tgico-check\"></span>\n <span class=\"tgico tgico-microphone\"></span>\n `);\n\n this.btnSendContainer.append(this.recordRippleEl, this.btnSend);\n\n if(this.chat.type !== 'scheduled') {\n this.sendMenu = new SendMenu({\n onSilentClick: () => {\n this.sendSilent = true;\n this.sendMessage();\n },\n onScheduleClick: () => {\n this.scheduleSending(undefined);\n },\n listenerSetter: this.listenerSetter,\n openSide: 'top-left',\n onContextElement: this.btnSend,\n onOpen: () => {\n return !this.isInputEmpty();\n }\n });\n \n this.btnSendContainer.append(this.sendMenu.sendMenu);\n }\n\n this.inputContainer.append(this.btnCancelRecord, this.btnSendContainer);\n\n emoticonsDropdown.attachButtonListener(this.btnToggleEmoticons, this.listenerSetter);\n emoticonsDropdown.events.onOpen.push(this.onEmoticonsOpen);\n emoticonsDropdown.events.onClose.push(this.onEmoticonsClose);\n\n this.attachMessageInputField();\n\n /* this.attachMenu.addEventListener('mousedown', (e) => {\n const hidden = this.attachMenu.querySelectorAll('.hide');\n if(hidden.length === this.attachMenuButtons.length) {\n toast(POSTING_MEDIA_NOT_ALLOWED);\n cancelEvent(e);\n return false;\n }\n }, {passive: false, capture: true}); */\n\n this.listenerSetter.add(rootScope, 'settings_updated', () => {\n if(this.stickersHelper) {\n if(!rootScope.settings.stickers.suggest) {\n this.stickersHelper.checkEmoticon('');\n } else {\n this.onMessageInput();\n }\n }\n\n if(this.messageInputField) {\n this.messageInputField.onFakeInput();\n }\n });\n\n this.listenerSetter.add(rootScope, 'draft_updated', (e) => {\n const {peerId, threadId, draft} = e;\n if(this.chat.threadId !== threadId || this.chat.peerId !== peerId) return;\n this.setDraft(draft);\n });\n\n this.listenerSetter.add(rootScope, 'peer_changing', (chat) => {\n if(this.chat === chat) {\n this.saveDraft();\n }\n });\n\n try {\n this.recorder = new Recorder({\n //encoderBitRate: 32,\n //encoderPath: \"../dist/encoderWorker.min.js\",\n encoderSampleRate: 48000,\n monitorGain: 0,\n numberOfChannels: 1,\n recordingGain: 1,\n reuseWorker: true\n });\n } catch(err) {\n console.error('Recorder constructor error:', err);\n }\n\n this.updateSendBtn();\n\n this.listenerSetter.add(this.fileInput, 'change', (e) => {\n let files = (e.target as HTMLInputElement & EventTarget).files;\n if(!files.length) {\n return;\n }\n \n new PopupNewMedia(this.chat, Array.from(files).slice(), this.willAttachType);\n this.fileInput.value = '';\n }, false);\n\n /* let time = Date.now();\n this.btnSend.addEventListener('touchstart', (e) => {\n time = Date.now();\n });\n\n let eventName1 = 'touchend';\n this.btnSend.addEventListener(eventName1, (e: Event) => {\n //cancelEvent(e);\n console.log(eventName1 + ', time: ' + (Date.now() - time));\n });\n\n let eventName = 'mousedown';\n this.btnSend.addEventListener(eventName, (e: Event) => {\n cancelEvent(e);\n console.log(eventName + ', time: ' + (Date.now() - time));\n }); */\n attachClickEvent(this.btnSend, this.onBtnSendClick, {listenerSetter: this.listenerSetter, touchMouseDown: true});\n\n if(this.recorder) {\n attachClickEvent(this.btnCancelRecord, this.onCancelRecordClick, {listenerSetter: this.listenerSetter});\n\n this.recorder.onstop = () => {\n this.recording = false;\n this.chatInput.classList.remove('is-recording', 'is-locked');\n this.updateSendBtn();\n this.recordRippleEl.style.transform = '';\n };\n \n this.recorder.ondataavailable = (typedArray: Uint8Array) => {\n if(this.recordCanceled) return;\n \n const duration = (Date.now() - this.recordStartTime) / 1000 | 0;\n const dataBlob = new Blob([typedArray], {type: 'audio/ogg'});\n /* const fileName = new Date().toISOString() + \".opus\";\n console.log('Recorder data received', typedArray, dataBlob); */\n\n //let perf = performance.now();\n opusDecodeController.decode(typedArray, true).then(result => {\n //console.log('WAVEFORM!:', /* waveform, */performance.now() - perf);\n \n opusDecodeController.setKeepAlive(false);\n \n let peerId = this.chat.peerId;\n // тут objectURL ставится уже с audio/wav\n this.appMessagesManager.sendFile(peerId, dataBlob, {\n isVoiceMessage: true,\n isMedia: true,\n duration,\n waveform: result.waveform,\n objectURL: result.url,\n replyToMsgId: this.replyToMsgId,\n threadId: this.chat.threadId,\n clearDraft: true\n });\n\n this.onMessageSent(false, true);\n });\n };\n }\n\n attachClickEvent(this.replyElements.cancelBtn, this.onHelperCancel, {listenerSetter: this.listenerSetter});\n attachClickEvent(this.replyElements.container, this.onHelperClick, {listenerSetter: this.listenerSetter});\n\n this.saveDraftDebounced = debounce(() => this.saveDraft(), 2500, false, true);\n }\n\n public constructPinnedHelpers() {\n const container = document.createElement('div');\n container.classList.add('pinned-container');\n\n this.pinnedControlBtn = Button('btn-primary btn-transparent text-bold pinned-container-button', {icon: 'unpin'});\n container.append(this.pinnedControlBtn);\n\n const fakeContainer = container.cloneNode(true);\n this.fakePinnedControlBtn = fakeContainer.firstChild as HTMLElement;\n this.fakeRowsWrapper.append(fakeContainer);\n\n this.listenerSetter.add(this.pinnedControlBtn, 'click', () => {\n const peerId = this.chat.peerId;\n\n new PopupPinMessage(peerId, 0, true, () => {\n this.chat.appImManager.setPeer(0); // * close tab\n\n // ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится\n const originalChat = this.chat.appImManager.chat;\n if(originalChat.topbar.pinnedMessage) {\n originalChat.topbar.pinnedMessage.pinnedMessageContainer.toggle(true);\n }\n });\n });\n\n this.rowsWrapper.append(container);\n\n this.chatInput.classList.add('type-pinned');\n this.rowsWrapper.classList.add('is-centered');\n }\n\n private onCancelRecordClick = (e?: Event) => {\n if(e) {\n cancelEvent(e);\n }\n \n this.recordCanceled = true;\n this.recorder.stop();\n opusDecodeController.setKeepAlive(false);\n };\n\n private onEmoticonsOpen = () => {\n const toggleClass = isTouchSupported ? 'flip-icon' : 'active';\n this.btnToggleEmoticons.classList.toggle(toggleClass, true);\n };\n\n private onEmoticonsClose = () => {\n const toggleClass = isTouchSupported ? 'flip-icon' : 'active';\n this.btnToggleEmoticons.classList.toggle(toggleClass, false);\n };\n\n public scheduleSending = (callback: () => void = this.sendMessage.bind(this, true), initDate = new Date()) => {\n new PopupSchedule(initDate, (timestamp) => {\n const minTimestamp = (Date.now() / 1000 | 0) + 10;\n if(timestamp <= minTimestamp) {\n timestamp = undefined;\n }\n\n this.scheduleDate = timestamp;\n callback();\n\n if(this.chat.type !== 'scheduled' && timestamp) {\n this.appImManager.openScheduled(this.chat.peerId);\n }\n }).show();\n };\n\n public setUnreadCount() {\n const dialog = this.appMessagesManager.getDialogByPeerId(this.chat.peerId)[0];\n const count = dialog?.unread_count;\n this.goDownUnreadBadge.innerText = '' + (count || '');\n this.goDownUnreadBadge.classList.toggle('badge-gray', this.appNotificationsManager.isPeerLocalMuted(this.chat.peerId, true));\n }\n\n public saveDraft() {\n if(!this.chat.peerId || this.editMsgId || this.chat.type === 'scheduled') return;\n \n const entities: MessageEntity[] = [];\n const str = getRichValue(this.messageInputField.input, entities);\n\n let draft: DraftMessage.draftMessage;\n if(str.length || this.replyToMsgId) {\n draft = {\n _: 'draftMessage',\n date: tsNow(true) + this.serverTimeManager.serverTimeOffset,\n message: str,\n entities: entities.length ? entities : undefined,\n pFlags: {\n no_webpage: this.noWebPage\n },\n reply_to_msg_id: this.replyToMsgId\n };\n }\n\n this.appDraftsManager.syncDraft(this.chat.peerId, this.chat.threadId, draft);\n }\n\n public destroy() {\n //this.chat.log.error('Input destroying');\n\n emoticonsDropdown.events.onOpen.findAndSplice(f => f === this.onEmoticonsOpen);\n emoticonsDropdown.events.onClose.findAndSplice(f => f === this.onEmoticonsClose);\n\n this.listenerSetter.removeAll();\n }\n\n public cleanup(helperToo = true) {\n if(!this.chat.peerId) {\n this.chatInput.style.display = 'none';\n this.goDownBtn.classList.add('hide');\n }\n\n cancelSelection();\n\n this.lastTimeType = 0;\n\n if(this.messageInput) {\n this.clearInput();\n helperToo && this.clearHelper();\n }\n }\n\n public setDraft(draft?: MyDraftMessage, fromUpdate = true) {\n if(!isInputEmpty(this.messageInput) || this.chat.type === 'scheduled') return false;\n \n if(!draft) {\n draft = this.appDraftsManager.getDraft(this.chat.peerId, this.chat.threadId);\n\n if(!draft) {\n return false;\n }\n }\n\n this.noWebPage = draft.pFlags.no_webpage;\n if(draft.reply_to_msg_id) {\n this.initMessageReply(draft.reply_to_msg_id);\n }\n\n this.setInputValue(draft.rMessage, fromUpdate, fromUpdate);\n return true;\n }\n\n public finishPeerChange() {\n const peerId = this.chat.peerId;\n\n this.chatInput.style.display = '';\n \n const isBroadcast = this.appPeersManager.isBroadcast(peerId);\n this.goDownBtn.classList.toggle('is-broadcast', isBroadcast);\n this.goDownBtn.classList.remove('hide');\n\n if(this.goDownUnreadBadge) {\n this.setUnreadCount();\n }\n\n if(this.chat.type === 'pinned') {\n this.chatInput.classList.toggle('can-pin', this.appPeersManager.canPinMessage(peerId));\n }/* else if(this.chat.type === 'chat') {\n } */\n\n if(this.btnScheduled) {\n this.btnScheduled.classList.add('hide');\n const middleware = this.chat.bubbles.getMiddleware();\n this.appMessagesManager.getScheduledMessages(peerId).then(mids => {\n if(!middleware()) return;\n this.btnScheduled.classList.toggle('hide', !mids.length);\n });\n }\n\n if(this.sendMenu) {\n this.sendMenu.setPeerId(peerId);\n }\n\n if(this.messageInput) {\n const canWrite = this.appMessagesManager.canWriteToPeer(peerId);\n this.chatInput.classList.add('no-transition');\n this.chatInput.classList.toggle('is-hidden', !canWrite);\n void this.chatInput.offsetLeft; // reflow\n this.chatInput.classList.remove('no-transition');\n\n const visible = this.attachMenuButtons.filter(button => {\n const good = button.verify(peerId);\n button.element.classList.toggle('hide', !good);\n return good;\n });\n \n if(!canWrite) {\n this.messageInput.removeAttribute('contenteditable');\n } else {\n this.messageInput.setAttribute('contenteditable', 'true');\n this.setDraft(undefined, false);\n\n if(!this.messageInput.innerHTML) {\n this.messageInputField.onFakeInput();\n }\n }\n \n this.attachMenu.toggleAttribute('disabled', !visible.length);\n this.updateSendBtn();\n } else if(this.pinnedControlBtn) {\n if(this.appPeersManager.canPinMessage(this.chat.peerId)) {\n this.pinnedControlBtn.append(i18n('Chat.Input.UnpinAll'));\n this.fakePinnedControlBtn.append(i18n('Chat.Input.UnpinAll'));\n } else {\n this.pinnedControlBtn.append(i18n('Chat.Pinned.DontShow'));\n this.fakePinnedControlBtn.append(i18n('Chat.Pinned.DontShow'));\n }\n }\n }\n\n private attachMessageInputField() {\n const oldInputField = this.messageInputField;\n this.messageInputField = new InputField({\n placeholder: 'Message',\n name: 'message',\n animate: true\n });\n\n this.messageInputField.input.classList.replace('input-field-input', 'input-message-input');\n this.messageInputField.inputFake.classList.replace('input-field-input', 'input-message-input');\n this.messageInput = this.messageInputField.input;\n this.attachMessageInputListeners();\n\n if(oldInputField) {\n oldInputField.input.replaceWith(this.messageInputField.input);\n oldInputField.inputFake.replaceWith(this.messageInputField.inputFake);\n } else {\n this.inputMessageContainer.append(this.messageInputField.input, this.messageInputField.inputFake);\n }\n }\n\n private attachMessageInputListeners() {\n this.listenerSetter.add(this.messageInput, 'keydown', (e: KeyboardEvent) => {\n if(isSendShortcutPressed(e)) {\n this.sendMessage();\n } else if(e.ctrlKey || e.metaKey) {\n this.handleMarkdownShortcut(e);\n }\n });\n\n if(isTouchSupported) {\n attachClickEvent(this.messageInput, (e) => {\n this.appImManager.selectTab(1); // * set chat tab for album orientation\n //this.saveScroll();\n emoticonsDropdown.toggle(false);\n }, {listenerSetter: this.listenerSetter});\n\n /* this.listenerSetter.add(window, 'resize', () => {\n this.restoreScroll();\n }); */\n\n /* if(isSafari) { \n this.listenerSetter.add(this.messageInput, 'mousedown', () => {\n window.requestAnimationFrame(() => {\n window.requestAnimationFrame(() => {\n emoticonsDropdown.toggle(false);\n });\n });\n });\n } */\n }\n\n /* this.listenerSetter.add(this.messageInput, 'beforeinput', (e: Event) => {\n // * validate due to manual formatting through browser's context menu\n const inputType = (e as InputEvent).inputType;\n //console.log('message beforeinput event', e);\n\n if(inputType.indexOf('format') === 0) {\n //console.log('message beforeinput format', e, inputType, this.messageInput.innerHTML);\n const markdownType = inputType.split('format')[1].toLowerCase() as MarkdownType;\n if(this.applyMarkdown(markdownType)) {\n cancelEvent(e); // * cancel legacy markdown event\n }\n }\n }); */\n this.listenerSetter.add(this.messageInput, 'input', this.onMessageInput);\n\n if(this.chat.type === 'chat' || this.chat.type === 'discussion') {\n this.listenerSetter.add(this.messageInput, 'focusin', () => {\n if(this.chat.bubbles.scrollable.loadedAll.bottom) {\n this.appMessagesManager.readAllHistory(this.chat.peerId, this.chat.threadId);\n }\n }); \n }\n }\n\n private prepareDocumentExecute = () => {\n this.executedHistory.push(this.messageInput.innerHTML);\n return () => this.canUndoFromHTML = this.messageInput.innerHTML;\n };\n\n private undoRedo = (e: Event, type: 'undo' | 'redo', needHTML: string) => {\n cancelEvent(e); // cancel legacy event\n\n let html = this.messageInput.innerHTML;\n if(html && html !== needHTML) {\n this.lockRedo = true;\n\n let sameHTMLTimes = 0;\n do {\n document.execCommand(type, false, null);\n const currentHTML = this.messageInput.innerHTML;\n if(html === currentHTML) {\n if(++sameHTMLTimes > 2) { // * unlink, removeFormat (а может и нет, случай: заболдить подчёркнутый текст (выделить ровно его), попробовать отменить)\n break;\n }\n } else {\n sameHTMLTimes = 0;\n }\n\n html = currentHTML;\n } while(html !== needHTML);\n\n this.lockRedo = false;\n }\n };\n\n public applyMarkdown(type: MarkdownType, href?: string) {\n const commandsMap: Partial<{[key in typeof type]: string | (() => void)}> = {\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strikethrough: 'Strikethrough',\n monospace: () => document.execCommand('fontName', false, 'monospace'),\n link: href ? () => document.execCommand('createLink', false, href) : () => document.execCommand('unlink', false, null)\n };\n\n if(!commandsMap[type]) {\n return false;\n }\n\n const command = commandsMap[type];\n\n //type = 'monospace';\n\n const saveExecuted = this.prepareDocumentExecute();\n const executed: any[] = [];\n /**\n * * clear previous formatting, due to Telegram's inability to handle several entities\n */\n /* const checkForSingle = () => {\n const nodes = getSelectedNodes();\n //console.log('Using formatting:', commandsMap[type], nodes, this.executedHistory);\n\n const parents = [...new Set(nodes.map(node => node.parentNode))];\n //const differentParents = !!nodes.find(node => node.parentNode !== firstParent);\n const differentParents = parents.length > 1;\n\n let notSingle = false;\n if(differentParents) {\n notSingle = true;\n } else {\n const node = nodes[0];\n if(node && (node.parentNode as HTMLElement) !== this.messageInput && (node.parentNode.parentNode as HTMLElement) !== this.messageInput) {\n notSingle = true;\n }\n }\n\n if(notSingle) {\n //if(type === 'monospace') {\n executed.push(document.execCommand('styleWithCSS', false, 'true'));\n //}\n\n executed.push(document.execCommand('unlink', false, null));\n executed.push(document.execCommand('removeFormat', false, null));\n executed.push(typeof(command) === 'function' ? command() : document.execCommand(command, false, null));\n\n //if(type === 'monospace') {\n executed.push(document.execCommand('styleWithCSS', false, 'false'));\n //}\n }\n }; */\n\n executed.push(document.execCommand('styleWithCSS', false, 'true'));\n \n if(type === 'monospace') {\n let haveThisType = false;\n //executed.push(document.execCommand('styleWithCSS', false, 'true'));\n\n const selection = window.getSelection();\n if(!selection.isCollapsed) {\n const range = selection.getRangeAt(0);\n const tag = markdownTags[type];\n\n const node = range.commonAncestorContainer;\n if((node.parentNode as HTMLElement).matches(tag.match) || (node instanceof HTMLElement && node.matches(tag.match))) {\n haveThisType = true;\n }\n }\n\n //executed.push(document.execCommand('removeFormat', false, null));\n\n if(haveThisType) {\n executed.push(document.execCommand('fontName', false, 'Roboto'));\n } else {\n executed.push(typeof(command) === 'function' ? command() : document.execCommand(command, false, null));\n }\n } else {\n executed.push(typeof(command) === 'function' ? command() : document.execCommand(command, false, null));\n }\n\n executed.push(document.execCommand('styleWithCSS', false, 'false'));\n\n //checkForSingle();\n saveExecuted();\n if(this.appImManager.markupTooltip) {\n this.appImManager.markupTooltip.setActiveMarkupButton();\n }\n\n return true;\n }\n\n private handleMarkdownShortcut = (e: KeyboardEvent) => {\n const formatKeys: {[key: string]: MarkdownType} = {\n 'B': 'bold',\n 'I': 'italic',\n 'U': 'underline',\n 'S': 'strikethrough',\n 'M': 'monospace',\n 'K': 'link'\n };\n\n const selection = document.getSelection();\n if(selection.toString().trim().length) {\n for(const key in formatKeys) {\n const good = e.code === ('Key' + key);\n \n if(good) {\n // * костыльчик\n if(key === 'K') {\n this.appImManager.markupTooltip.showLinkEditor();\n cancelEvent(e);\n break;\n }\n \n this.applyMarkdown(formatKeys[key]);\n cancelEvent(e); // cancel legacy event\n break;\n }\n }\n }\n\n //return;\n if(e.code === 'KeyZ') {\n let html = this.messageInput.innerHTML;\n\n if(e.shiftKey) {\n if(this.undoHistory.length) {\n this.executedHistory.push(html);\n html = this.undoHistory.pop();\n this.undoRedo(e, 'redo', html);\n html = this.messageInput.innerHTML;\n this.canRedoFromHTML = this.undoHistory.length ? html : '';\n this.canUndoFromHTML = html;\n }\n } else {\n // * подождём, когда пользователь сам восстановит поле до нужного состояния, которое стало сразу после saveExecuted\n if(this.executedHistory.length && (!this.canUndoFromHTML || html === this.canUndoFromHTML)) {\n this.undoHistory.push(html);\n html = this.executedHistory.pop();\n this.undoRedo(e, 'undo', html);\n\n // * поставим новое состояние чтобы снова подождать, если пользователь изменит что-то, и потом попробует откатить до предыдущего состояния\n this.canUndoFromHTML = this.canRedoFromHTML = this.messageInput.innerHTML;\n }\n }\n }\n };\n\n private onMessageInput = (e?: Event) => {\n // * validate due to manual formatting through browser's context menu\n /* const inputType = (e as InputEvent).inputType;\n console.log('message input event', e);\n if(inputType === 'formatBold') {\n console.log('message input format', this.messageInput.innerHTML);\n cancelEvent(e);\n }\n\n if(!isSelectionSingle()) {\n alert('not single');\n } */\n\n //console.log('messageInput input', this.messageInput.innerText);\n //const value = this.messageInput.innerText;\n const markdownEntities: MessageEntity[] = [];\n const richValue = getRichValue(this.messageInputField.input, markdownEntities);\n \n //const entities = RichTextProcessor.parseEntities(value);\n const value = RichTextProcessor.parseMarkdown(richValue, markdownEntities);\n const entities = RichTextProcessor.mergeEntities(markdownEntities, RichTextProcessor.parseEntities(value));\n\n //this.chat.log('messageInput entities', richValue, value, markdownEntities);\n\n if(this.stickersHelper && \n rootScope.settings.stickers.suggest && \n (this.chat.peerId > 0 || this.appChatsManager.hasRights(this.chat.peerId, 'send_stickers'))) {\n let emoticon = '';\n if(entities.length && entities[0]._ === 'messageEntityEmoji') {\n const entity = entities[0];\n if(entity.length === richValue.length && !entity.offset) {\n emoticon = richValue;\n }\n }\n\n this.stickersHelper.checkEmoticon(emoticon);\n }\n\n if(!richValue.trim()) {\n this.appImManager.markupTooltip.hide();\n }\n\n const html = this.messageInput.innerHTML;\n if(this.canRedoFromHTML && html !== this.canRedoFromHTML && !this.lockRedo) {\n this.canRedoFromHTML = '';\n this.undoHistory.length = 0;\n }\n\n const urlEntities: Array<MessageEntity.messageEntityUrl | MessageEntity.messageEntityTextUrl> = entities.filter(e => e._ === 'messageEntityUrl' || e._ === 'messageEntityTextUrl') as any;\n if(urlEntities.length) {\n for(const entity of urlEntities) {\n let url: string;\n if(entity._ === 'messageEntityTextUrl') {\n url = entity.url;\n } else {\n url = richValue.slice(entity.offset, entity.offset + entity.length);\n\n if(!(url.includes('http://') || url.includes('https://'))) {\n continue;\n }\n }\n\n //console.log('messageInput url:', url);\n\n if(this.lastUrl !== url) {\n this.lastUrl = url;\n this.willSendWebPage = null;\n apiManager.invokeApi('messages.getWebPage', {\n url,\n hash: 0\n }).then((webpage) => {\n webpage = this.appWebPagesManager.saveWebPage(webpage);\n if(webpage._ === 'webPage') {\n if(this.lastUrl !== url) return;\n //console.log('got webpage: ', webpage);\n\n this.setTopInfo('webpage', () => {}, webpage.site_name || webpage.title || 'Webpage', webpage.description || webpage.url || '');\n\n delete this.noWebPage;\n this.willSendWebPage = webpage;\n }\n });\n }\n\n break;\n }\n } else if(this.lastUrl) {\n this.lastUrl = '';\n delete this.noWebPage;\n this.willSendWebPage = null;\n \n if(this.helperType) {\n this.helperFunc();\n } else {\n this.clearHelper();\n }\n }\n\n if(this.isInputEmpty()) {\n if(this.lastTimeType) {\n this.appMessagesManager.setTyping(this.chat.peerId, 'sendMessageCancelAction');\n }\n } else {\n const time = Date.now();\n if(time - this.lastTimeType >= 6000) {\n this.lastTimeType = time;\n this.appMessagesManager.setTyping(this.chat.peerId, 'sendMessageTypingAction');\n }\n }\n\n if(!this.editMsgId) {\n this.saveDraftDebounced();\n }\n\n this.updateSendBtn();\n };\n\n private onBtnSendClick = (e: Event) => {\n cancelEvent(e);\n\n if(!this.recorder || this.recording || !this.isInputEmpty() || this.forwardingMids.length || this.editMsgId) {\n if(this.recording) {\n if((Date.now() - this.recordStartTime) < RECORD_MIN_TIME) {\n this.onCancelRecordClick();\n } else {\n this.recorder.stop();\n }\n } else {\n this.sendMessage();\n }\n } else {\n if(this.chat.peerId < 0 && !this.appChatsManager.hasRights(this.chat.peerId, 'send_media')) {\n toast(POSTING_MEDIA_NOT_ALLOWED);\n return;\n }\n\n this.chatInput.classList.add('is-locked');\n blurActiveElement();\n this.recorder.start().then(() => {\n this.recordCanceled = false;\n \n this.chatInput.classList.add('is-recording');\n this.recording = true;\n this.updateSendBtn();\n opusDecodeController.setKeepAlive(true);\n\n this.recordStartTime = Date.now();\n\n const sourceNode: MediaStreamAudioSourceNode = this.recorder.sourceNode;\n const context = sourceNode.context;\n\n const analyser = context.createAnalyser();\n sourceNode.connect(analyser);\n //analyser.connect(context.destination);\n analyser.fftSize = 32;\n\n const frequencyData = new Uint8Array(analyser.frequencyBinCount);\n const max = frequencyData.length * 255;\n const min = 54 / 150;\n let r = () => {\n if(!this.recording) return;\n\n analyser.getByteFrequencyData(frequencyData);\n\n let sum = 0;\n frequencyData.forEach(value => {\n sum += value;\n });\n \n let percents = Math.min(1, (sum / max) + min);\n //console.log('frequencyData', frequencyData, percents);\n\n this.recordRippleEl.style.transform = `scale(${percents})`;\n\n let diff = Date.now() - this.recordStartTime;\n let ms = diff % 1000;\n\n let formatted = ('' + (diff / 1000)).toHHMMSS() + ',' + ('00' + Math.round(ms / 10)).slice(-2);\n\n this.recordTimeEl.innerText = formatted;\n\n window.requestAnimationFrame(r);\n };\n\n r();\n }).catch((e: Error) => {\n switch(e.name as string) {\n case 'NotAllowedError': {\n toast('Please allow access to your microphone');\n break;\n }\n\n case 'NotReadableError': {\n toast(e.message);\n break;\n }\n\n default:\n console.error('Recorder start error:', e, e.name, e.message);\n toast(e.message);\n break;\n }\n\n this.chatInput.classList.remove('is-recording', 'is-locked');\n });\n }\n };\n\n private onHelperCancel = (e?: Event) => {\n if(e) {\n cancelEvent(e);\n }\n\n if(this.willSendWebPage) {\n const lastUrl = this.lastUrl;\n let needReturn = false;\n if(this.helperType) {\n //if(this.helperFunc) {\n this.helperFunc();\n //}\n\n needReturn = true;\n }\n\n // * restore values\n this.lastUrl = lastUrl;\n this.noWebPage = true;\n this.willSendWebPage = null;\n\n if(needReturn) return;\n }\n\n this.clearHelper();\n this.updateSendBtn();\n };\n\n private onHelperClick = (e: Event) => {\n cancelEvent(e);\n \n if(!findUpClassName(e.target, 'reply-wrapper')) return;\n if(this.helperType === 'forward') {\n if(this.helperWaitingForward) return;\n this.helperWaitingForward = true;\n\n const fromId = this.forwardingFromPeerId;\n const mids = this.forwardingMids.slice();\n const helperFunc = this.helperFunc;\n this.clearHelper();\n let selected = false;\n new PopupForward(fromId, mids, () => {\n selected = true;\n }, () => {\n this.helperWaitingForward = false;\n\n if(!selected) {\n helperFunc();\n }\n });\n } else if(this.helperType === 'reply') {\n this.chat.setMessageId(this.replyToMsgId);\n } else if(this.helperType === 'edit') {\n this.chat.setMessageId(this.editMsgId);\n }\n };\n\n public clearInput(canSetDraft = true) {\n this.messageInputField.value = '';\n if(isTouchSupported) {\n //this.messageInput.innerText = '';\n } else {\n //this.attachMessageInputField();\n //this.messageInput.innerText = '';\n\n // clear executions\n this.canRedoFromHTML = '';\n this.undoHistory.length = 0;\n this.executedHistory.length = 0;\n this.canUndoFromHTML = '';\n }\n\n let set = false;\n if(canSetDraft) {\n set = this.setDraft(undefined, false);\n }\n\n /* if(!set) {\n this.onMessageInput();\n } */\n }\n\n public isInputEmpty() {\n return isInputEmpty(this.messageInput);\n }\n\n public updateSendBtn() {\n let icon: 'send' | 'record' | 'edit' | 'schedule';\n\n const isInputEmpty = this.isInputEmpty();\n\n if(this.editMsgId) icon = 'edit';\n else if(!this.recorder || this.recording || !isInputEmpty || this.forwardingMids.length) icon = this.chat.type === 'scheduled' ? 'schedule' : 'send';\n else icon = 'record';\n\n ['send', 'record', 'edit', 'schedule'].forEach(i => {\n this.btnSend.classList.toggle(i, icon === i);\n });\n\n if(this.btnScheduled) {\n this.btnScheduled.classList.toggle('show', isInputEmpty);\n }\n }\n\n public onMessageSent(clearInput = true, clearReply?: boolean) {\n if(this.chat.type !== 'scheduled') {\n this.appMessagesManager.readAllHistory(this.chat.peerId, this.chat.threadId, true);\n }\n\n this.scheduleDate = undefined;\n this.sendSilent = undefined;\n\n if(clearInput) {\n this.lastUrl = '';\n delete this.noWebPage;\n this.willSendWebPage = null;\n this.clearInput();\n }\n\n if(clearReply || clearInput) {\n this.clearHelper();\n }\n\n this.updateSendBtn();\n }\n\n public sendMessage(force = false) {\n if(this.chat.type === 'scheduled' && !force && !this.editMsgId) {\n this.scheduleSending();\n return;\n }\n\n const entities: MessageEntity[] = [];\n const str = getRichValue(this.messageInputField.input, entities);\n\n //return;\n if(this.editMsgId) {\n this.appMessagesManager.editMessage(this.chat.getMessage(this.editMsgId), str, {\n entities,\n noWebPage: this.noWebPage\n });\n } else {\n this.appMessagesManager.sendText(this.chat.peerId, str, {\n entities,\n replyToMsgId: this.replyToMsgId,\n threadId: this.chat.threadId,\n noWebPage: this.noWebPage,\n webPage: this.willSendWebPage,\n scheduleDate: this.scheduleDate,\n silent: this.sendSilent,\n clearDraft: true\n });\n }\n\n // * wait for sendText set messageId for invokeAfterMsg\n if(this.forwardingMids.length) {\n const mids = this.forwardingMids.slice();\n const fromPeerId = this.forwardingFromPeerId;\n const peerId = this.chat.peerId;\n const silent = this.sendSilent;\n const scheduleDate = this.scheduleDate;\n setTimeout(() => {\n this.appMessagesManager.forwardMessages(peerId, fromPeerId, mids, {\n silent,\n scheduleDate: scheduleDate\n });\n }, 0);\n }\n\n this.onMessageSent();\n }\n\n public sendMessageWithDocument(document: MyDocument | string, force = false, clearDraft = false) {\n document = this.appDocsManager.getDoc(document);\n\n const flag = document.type === 'sticker' ? 'send_stickers' : (document.type === 'gif' ? 'send_gifs' : 'send_media');\n if(this.chat.peerId < 0 && !this.appChatsManager.hasRights(this.chat.peerId, flag)) {\n toast(POSTING_MEDIA_NOT_ALLOWED);\n return;\n }\n\n if(this.chat.type === 'scheduled' && !force) {\n this.scheduleSending(() => this.sendMessageWithDocument(document, true));\n return false;\n }\n\n if(document) {\n this.appMessagesManager.sendFile(this.chat.peerId, document, {\n isMedia: true, \n replyToMsgId: this.replyToMsgId, \n threadId: this.chat.threadId,\n silent: this.sendSilent, \n scheduleDate: this.scheduleDate,\n clearDraft: clearDraft || undefined\n });\n this.onMessageSent(clearDraft, true);\n\n if(document.type === 'sticker') {\n emoticonsDropdown.stickersTab?.pushRecentSticker(document);\n }\n\n return true;\n }\n \n return false;\n }\n\n /* public sendSomething(callback: () => void, force = false) {\n if(this.chat.type === 'scheduled' && !force) {\n this.scheduleSending(() => this.sendSomething(callback, true));\n return false;\n }\n\n callback();\n this.onMessageSent(false, true);\n\n return true;\n } */\n\n public initMessageEditing(mid: number) {\n const message = this.chat.getMessage(mid);\n\n let input = RichTextProcessor.wrapDraftText(message.message, {entities: message.totalEntities});\n const f = () => {\n // ! костыль\n const replyFragment = this.appMessagesManager.wrapMessageForReply(message, undefined, [message.mid]);\n this.setTopInfo('edit', f, 'Editing', undefined, input, message);\n const subtitleEl = this.replyElements.container.querySelector('.reply-subtitle');\n subtitleEl.textContent = '';\n subtitleEl.append(replyFragment);\n\n this.editMsgId = mid;\n input = undefined;\n };\n f();\n }\n\n public initMessagesForward(fromPeerId: number, mids: number[]) {\n const f = () => {\n //const peerTitles: string[]\n const smth: Set<string | number> = new Set(mids.map(mid => {\n const message = this.appMessagesManager.getMessageByPeer(fromPeerId, mid);\n if(message.fwd_from && message.fwd_from.from_name && !message.fromId && !message.fwdFromId) {\n return message.fwd_from.from_name;\n } else {\n return message.fromId;\n }\n }));\n\n const onlyFirstName = smth.size > 1;\n const peerTitles = [...smth].map(smth => {\n return typeof(smth) === 'number' ? \n this.appPeersManager.getPeerTitle(smth, true, onlyFirstName) : \n (onlyFirstName ? smth.split(' ')[0] : smth);\n });\n\n const title = peerTitles.length < 3 ? peerTitles.join(' and ') : peerTitles[0] + ' and ' + (peerTitles.length - 1) + ' others';\n const firstMessage = this.appMessagesManager.getMessageByPeer(fromPeerId, mids[0]);\n\n let usingFullAlbum = true;\n if(firstMessage.grouped_id) {\n const albumMids = this.appMessagesManager.getMidsByMessage(firstMessage);\n if(albumMids.length !== mids.length || albumMids.find(mid => !mids.includes(mid))) {\n usingFullAlbum = false;\n }\n }\n\n const replyFragment = this.appMessagesManager.wrapMessageForReply(firstMessage, undefined, mids);\n if(usingFullAlbum || mids.length === 1) {\n this.setTopInfo('forward', f, title);\n\n // ! костыль\n const subtitleEl = this.replyElements.container.querySelector('.reply-subtitle');\n subtitleEl.textContent = '';\n subtitleEl.append(replyFragment);\n } else {\n this.setTopInfo('forward', f, title, mids.length + ' ' + (mids.length > 1 ? 'forwarded messages' : 'forwarded message'));\n }\n\n this.forwardingMids = mids.slice();\n this.forwardingFromPeerId = fromPeerId;\n };\n \n f();\n }\n\n public initMessageReply(mid: number) {\n const message = this.chat.getMessage(mid);\n const f = () => {\n this.setTopInfo('reply', f, this.appPeersManager.getPeerTitle(message.fromId, true), message.message, undefined, message);\n this.replyToMsgId = mid;\n };\n f();\n }\n\n public clearHelper(type?: ChatInputHelperType) {\n if(this.helperType === 'edit' && type !== 'edit') {\n this.clearInput();\n }\n\n if(type) {\n this.lastUrl = '';\n delete this.noWebPage;\n this.willSendWebPage = null;\n }\n \n this.replyToMsgId = undefined;\n this.forwardingMids.length = 0;\n this.forwardingFromPeerId = 0;\n this.editMsgId = undefined;\n this.helperType = this.helperFunc = undefined;\n\n if(this.chat.container.classList.contains('is-helper-active')) {\n appNavigationController.removeByType('input-helper');\n this.chat.container.classList.remove('is-helper-active');\n }\n }\n\n public setInputValue(value: string, clear = true, focus = true) {\n clear && this.clearInput();\n this.messageInputField.value = value || '';\n window.requestAnimationFrame(() => {\n focus && placeCaretAtEnd(this.messageInput);\n this.messageInput.scrollTop = this.messageInput.scrollHeight;\n });\n }\n\n public setTopInfo(type: ChatInputHelperType, callerFunc: () => void, title = '', subtitle = '', input?: string, message?: any) {\n if(type !== 'webpage') {\n this.clearHelper(type);\n this.helperType = type;\n this.helperFunc = callerFunc;\n }\n\n if(this.replyElements.container.lastElementChild.tagName === 'DIV') {\n this.replyElements.container.lastElementChild.remove();\n this.replyElements.container.append(wrapReply(title, subtitle, message));\n }\n\n this.chat.container.classList.add('is-helper-active');\n /* const scroll = appImManager.scrollable;\n if(scroll.isScrolledDown && !scroll.scrollLocked && !appImManager.messagesQueuePromise && !appImManager.setPeerPromise) {\n scroll.scrollTo(scroll.scrollHeight, 'top', true, true, 200);\n } */\n\n if(!isMobile) {\n appNavigationController.pushItem({\n type: 'input-helper',\n onPop: () => {\n this.onHelperCancel();\n }\n });\n }\n\n if(input !== undefined) {\n this.setInputValue(input);\n }\n\n setTimeout(() => {\n this.updateSendBtn();\n }, 0);\n }\n\n // public saveScroll() {\n // this.scrollTop = this.chat.bubbles.scrollable.container.scrollTop;\n // this.scrollOffsetTop = this.chatInput.offsetTop;\n // }\n\n // public restoreScroll() {\n // if(this.chatInput.style.display) return;\n // //console.log('input resize', offsetTop, this.chatInput.offsetTop);\n // let newOffsetTop = this.chatInput.offsetTop;\n // let container = this.chat.bubbles.scrollable.container;\n // let scrollTop = container.scrollTop;\n // let clientHeight = container.clientHeight;\n // let maxScrollTop = container.scrollHeight;\n\n // if(newOffsetTop < this.scrollOffsetTop) {\n // this.scrollDiff = this.scrollOffsetTop - newOffsetTop;\n // container.scrollTop += this.scrollDiff;\n // } else if(scrollTop !== this.scrollTop) {\n // let endDiff = maxScrollTop - (scrollTop + clientHeight);\n // if(endDiff < this.scrollDiff/* && false */) {\n // //container.scrollTop -= endDiff;\n // } else {\n // container.scrollTop -= this.scrollDiff;\n // }\n // }\n // }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type ChatBubbles from \"./bubbles\";\nimport type ChatInput from \"./input\";\nimport type Chat from \"./chat\";\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport { blurActiveElement, cancelEvent, cancelSelection, getSelectedText } from \"../../helpers/dom\";\nimport Button from \"../button\";\nimport ButtonIcon from \"../buttonIcon\";\nimport CheckboxField from \"../checkboxField\";\nimport PopupDeleteMessages from \"../popups/deleteMessages\";\nimport PopupForward from \"../popups/forward\";\nimport { toast } from \"../toast\";\nimport SetTransition from \"../singleTransition\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\nimport PopupSendNow from \"../popups/sendNow\";\nimport appNavigationController from \"../appNavigationController\";\nimport { isMobileSafari } from \"../../helpers/userAgent\";\nimport I18n, { i18n, _i18n } from \"../../lib/langPack\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\n\nconst MAX_SELECTION_LENGTH = 100;\n//const MIN_CLICK_MOVE = 32; // minimum bubble height\n\nexport default class ChatSelection {\n public selectedMids: Set<number> = new Set();\n public isSelecting = false;\n\n private selectionInputWrapper: HTMLElement;\n private selectionContainer: HTMLElement;\n private selectionCountEl: HTMLElement;\n public selectionSendNowBtn: HTMLElement;\n public selectionForwardBtn: HTMLElement;\n public selectionDeleteBtn: HTMLElement;\n\n public selectedText: string;\n\n private listenerSetter: ListenerSetter;\n\n constructor(private chat: Chat, private bubbles: ChatBubbles, private input: ChatInput, private appMessagesManager: AppMessagesManager) {\n const bubblesContainer = bubbles.bubblesContainer;\n this.listenerSetter = bubbles.listenerSetter;\n\n if(isTouchSupported) {\n this.listenerSetter.add(bubblesContainer, 'touchend', (e) => {\n if(!this.isSelecting) return;\n this.selectedText = getSelectedText();\n });\n return;\n }\n\n this.listenerSetter.add(bubblesContainer, 'mousedown', (e) => {\n //console.log('selection mousedown', e);\n const bubble = findUpClassName(e.target, 'bubble');\n // LEFT BUTTON\n // проверка внизу нужна для того, чтобы не активировать селект если target потомок .bubble\n if(e.button !== 0\n || (\n !this.selectedMids.size \n && !(e.target as HTMLElement).classList.contains('bubble')\n && !(e.target as HTMLElement).classList.contains('document-selection')\n && bubble\n )\n ) {\n return;\n }\n \n const seen: Set<number> = new Set();\n let selecting: boolean;\n\n /* let good = false;\n const {x, y} = e; */\n\n /* const bubbles = appImManager.bubbles;\n for(const mid in bubbles) {\n const bubble = bubbles[mid];\n bubble.addEventListener('mouseover', () => {\n console.log('mouseover');\n }, {once: true});\n } */\n\n //const foundTargets: Map<HTMLElement, true> = new Map();\n let canceledSelection = false;\n const onMouseMove = (e: MouseEvent) => {\n if(!canceledSelection) {\n cancelSelection();\n canceledSelection = true;\n }\n /* if(!good) {\n if(Math.abs(e.x - x) > MIN_CLICK_MOVE || Math.abs(e.y - y) > MIN_CLICK_MOVE) {\n good = true;\n } else {\n return;\n }\n } */\n\n /* if(foundTargets.has(e.target as HTMLElement)) return;\n foundTargets.set(e.target as HTMLElement, true); */\n const bubble = findUpClassName(e.target, 'grouped-item') || findUpClassName(e.target, 'bubble');\n if(!bubble) {\n //console.error('found no bubble', e);\n return;\n }\n\n const mid = +bubble.dataset.mid;\n if(!mid) return;\n\n // * cancel selecting if selecting message text\n if(e.target !== bubble && !(e.target as HTMLElement).classList.contains('document-selection') && selecting === undefined && !this.selectedMids.size) {\n this.listenerSetter.removeManual(bubblesContainer, 'mousemove', onMouseMove);\n this.listenerSetter.removeManual(document, 'mouseup', onMouseUp, documentListenerOptions);\n return;\n }\n\n if(!seen.has(mid)) {\n const isBubbleSelected = this.selectedMids.has(mid);\n if(selecting === undefined) {\n //bubblesContainer.classList.add('no-select');\n selecting = !isBubbleSelected;\n }\n\n seen.add(mid);\n\n if((selecting && !isBubbleSelected) || (!selecting && isBubbleSelected)) {\n if(!this.selectedMids.size) {\n if(seen.size === 2) {\n [...seen].forEach(mid => {\n const mounted = this.bubbles.getMountedBubble(mid);\n if(mounted) {\n this.toggleByBubble(mounted.bubble);\n }\n })\n }\n } else {\n this.toggleByBubble(bubble);\n }\n }\n }\n //console.log('onMouseMove', target);\n };\n\n const onMouseUp = (e: MouseEvent) => {\n if(seen.size) {\n window.addEventListener('click', (e) => {\n cancelEvent(e);\n }, {capture: true, once: true, passive: false});\n }\n\n this.listenerSetter.removeManual(bubblesContainer, 'mousemove', onMouseMove);\n //bubblesContainer.classList.remove('no-select');\n\n // ! CANCEL USER SELECTION !\n cancelSelection();\n };\n\n const documentListenerOptions = {once: true};\n this.listenerSetter.add(bubblesContainer, 'mousemove', onMouseMove);\n this.listenerSetter.add(document, 'mouseup', onMouseUp, documentListenerOptions);\n });\n }\n\n public toggleBubbleCheckbox(bubble: HTMLElement, show: boolean) {\n if(!this.canSelectBubble(bubble)) return;\n\n const hasCheckbox = !!this.getCheckboxInputFromBubble(bubble);\n const isGrouped = bubble.classList.contains('is-grouped');\n if(show) {\n if(hasCheckbox) return;\n \n const checkboxField = new CheckboxField({\n name: bubble.dataset.mid, \n round: true\n });\n checkboxField.label.classList.add('bubble-select-checkbox');\n\n // * if it is a render of new message\n if(this.isSelecting) { // ! avoid breaking animation on start\n const mid = +bubble.dataset.mid;\n if(this.selectedMids.has(mid) && (!isGrouped || this.isGroupedMidsSelected(mid))) {\n checkboxField.input.checked = true;\n bubble.classList.add('is-selected');\n }\n }\n\n if(bubble.classList.contains('document-container')) {\n bubble.querySelector('.document, audio-element').append(checkboxField.label);\n } else {\n bubble.prepend(checkboxField.label);\n }\n } else if(hasCheckbox) {\n this.getCheckboxInputFromBubble(bubble).parentElement.remove();\n }\n\n if(isGrouped) {\n this.bubbles.getBubbleGroupedItems(bubble).forEach(item => this.toggleBubbleCheckbox(item, show));\n }\n }\n\n private getCheckboxInputFromBubble(bubble: HTMLElement): HTMLInputElement {\n /* let perf = performance.now();\n let checkbox = bubble.firstElementChild.tagName === 'LABEL' && bubble.firstElementChild.firstElementChild as HTMLInputElement;\n console.log('getCheckboxInputFromBubble firstElementChild time:', performance.now() - perf);\n\n perf = performance.now();\n checkbox = bubble.querySelector('label input');\n console.log('getCheckboxInputFromBubble querySelector time:', performance.now() - perf); */\n /* let perf = performance.now();\n let contains = bubble.classList.contains('document-container');\n console.log('getCheckboxInputFromBubble classList time:', performance.now() - perf);\n\n perf = performance.now();\n contains = bubble.className.includes('document-container');\n console.log('getCheckboxInputFromBubble className time:', performance.now() - perf); */\n\n return bubble.classList.contains('document-container') ? \n bubble.querySelector('label input') : \n bubble.firstElementChild.tagName === 'LABEL' && bubble.firstElementChild.firstElementChild as HTMLInputElement;\n }\n\n private updateContainer(forceSelection = false) {\n if(!this.selectedMids.size && !forceSelection) return;\n this.selectionCountEl.textContent = '';\n this.selectionCountEl.append(i18n('Chat.Selection.MessagesCount', [this.selectedMids.size]));\n\n let cantForward = !this.selectedMids.size, cantDelete = !this.selectedMids.size, cantSend = !this.selectedMids.size;\n for(const mid of this.selectedMids.values()) {\n const message = this.appMessagesManager.getMessageByPeer(this.bubbles.peerId, mid);\n if(!cantForward) {\n if(message.action) {\n cantForward = true;\n }\n }\n \n\n if(!cantDelete) {\n const canDelete = this.appMessagesManager.canDeleteMessage(this.chat.getMessage(mid));\n if(!canDelete) {\n cantDelete = true;\n }\n }\n\n if(cantForward && cantDelete) break;\n }\n\n this.selectionSendNowBtn && this.selectionSendNowBtn.toggleAttribute('disabled', cantSend);\n this.selectionForwardBtn && this.selectionForwardBtn.toggleAttribute('disabled', cantForward);\n this.selectionDeleteBtn.toggleAttribute('disabled', cantDelete);\n }\n\n public toggleSelection(toggleCheckboxes = true, forceSelection = false) {\n const wasSelecting = this.isSelecting;\n this.isSelecting = this.selectedMids.size > 0 || forceSelection;\n\n if(wasSelecting === this.isSelecting) return;\n \n const bubblesContainer = this.bubbles.bubblesContainer;\n //bubblesContainer.classList.toggle('is-selecting', !!this.selectedMids.size);\n\n /* if(bubblesContainer.classList.contains('is-chat-input-hidden')) {\n const scrollable = this.appImManager.scrollable;\n if(scrollable.isScrolledDown) {\n scrollable.scrollTo(scrollable.scrollHeight, 'top', true, true, 200);\n }\n } */\n\n if(!isTouchSupported) {\n bubblesContainer.classList.toggle('no-select', this.isSelecting);\n\n if(wasSelecting) {\n // ! CANCEL USER SELECTION !\n cancelSelection();\n }\n }/* else {\n if(!wasSelecting) {\n bubblesContainer.classList.add('no-select');\n setTimeout(() => {\n cancelSelection();\n bubblesContainer.classList.remove('no-select');\n cancelSelection();\n }, 100);\n }\n } */\n\n blurActiveElement(); // * for mobile keyboards\n\n let transform = '', borderRadius = '';\n const forwards = !!this.selectedMids.size || forceSelection;\n if(forwards) {\n const p = this.input.rowsWrapper.parentElement;\n const fakeSelectionWrapper = p.querySelector('.fake-selection-wrapper');\n const fakeRowsWrapper = p.querySelector('.fake-rows-wrapper');\n const fakeSelectionRect = fakeSelectionWrapper.getBoundingClientRect();\n const fakeRowsRect = fakeRowsWrapper.getBoundingClientRect();\n const widthFrom = fakeRowsRect.width;\n const widthTo = fakeSelectionRect.width;\n\n if(widthFrom !== widthTo) {\n const scale = (widthTo/* - 8 */) / widthFrom;\n const initTranslateX = (widthFrom - widthTo) / 2;\n const needTranslateX = fakeSelectionRect.left - fakeRowsRect.left - initTranslateX;\n transform = `translateX(${needTranslateX}px) scaleX(${scale})`;\n\n if(scale < 1) {\n const br = 12;\n borderRadius = '' + (br + br * (1 - scale)) + 'px';\n }\n //scale = widthTo / widthFrom;\n }\n }\n\n SetTransition(this.input.rowsWrapper, 'is-centering', forwards, 200);\n this.input.rowsWrapper.style.transform = transform;\n this.input.rowsWrapper.style.borderRadius = borderRadius;\n SetTransition(bubblesContainer, 'is-selecting', forwards, 200, () => {\n if(!this.isSelecting) {\n this.selectionInputWrapper.remove();\n this.selectionInputWrapper = this.selectionContainer = this.selectionSendNowBtn = this.selectionForwardBtn = this.selectionDeleteBtn = null;\n this.selectedText = undefined;\n }\n \n window.requestAnimationFrame(() => {\n this.bubbles.onScroll();\n });\n });\n\n if(!isMobileSafari) {\n if(forwards) {\n appNavigationController.pushItem({\n type: 'multiselect',\n onPop: () => {\n this.cancelSelection();\n }\n });\n } else {\n appNavigationController.removeByType('multiselect');\n }\n }\n\n //const chatInput = this.appImManager.chatInput;\n\n if(this.isSelecting) {\n if(!this.selectionContainer) {\n this.selectionInputWrapper = document.createElement('div');\n this.selectionInputWrapper.classList.add('chat-input-wrapper', 'selection-wrapper');\n\n this.selectionContainer = document.createElement('div');\n this.selectionContainer.classList.add('selection-container');\n\n const btnCancel = ButtonIcon('close', {noRipple: true});\n this.listenerSetter.add(btnCancel, 'click', this.cancelSelection, {once: true});\n\n this.selectionCountEl = document.createElement('div');\n this.selectionCountEl.classList.add('selection-container-count');\n\n if(this.chat.type === 'scheduled') {\n this.selectionSendNowBtn = Button('btn-primary btn-transparent btn-short text-bold selection-container-send', {icon: 'send2'});\n this.selectionSendNowBtn.append(i18n('Chat.Context.Scheduled.SendNow'));\n this.listenerSetter.add(this.selectionSendNowBtn, 'click', () => {\n new PopupSendNow(this.bubbles.peerId, [...this.selectedMids], () => {\n this.cancelSelection();\n })\n });\n } else {\n this.selectionForwardBtn = Button('btn-primary btn-transparent text-bold selection-container-forward', {icon: 'forward'});\n this.selectionForwardBtn.append(i18n('Forward'));\n this.listenerSetter.add(this.selectionForwardBtn, 'click', () => {\n new PopupForward(this.bubbles.peerId, [...this.selectedMids], () => {\n this.cancelSelection();\n });\n });\n }\n\n this.selectionDeleteBtn = Button('btn-primary btn-transparent danger text-bold selection-container-delete', {icon: 'delete'});\n this.selectionDeleteBtn.append(i18n('Delete'));\n this.listenerSetter.add(this.selectionDeleteBtn, 'click', () => {\n new PopupDeleteMessages(this.bubbles.peerId, [...this.selectedMids], this.chat.type, () => {\n this.cancelSelection();\n });\n });\n\n this.selectionContainer.append(...[btnCancel, this.selectionCountEl, this.selectionSendNowBtn, this.selectionForwardBtn, this.selectionDeleteBtn].filter(Boolean));\n\n this.selectionInputWrapper.style.opacity = '0';\n this.selectionInputWrapper.append(this.selectionContainer);\n this.input.rowsWrapper.parentElement.append(this.selectionInputWrapper);\n\n void this.selectionInputWrapper.offsetLeft; // reflow\n this.selectionInputWrapper.style.opacity = '';\n }\n }\n\n if(toggleCheckboxes) {\n for(const mid in this.bubbles.bubbles) {\n const bubble = this.bubbles.bubbles[mid];\n this.toggleBubbleCheckbox(bubble, this.isSelecting);\n }\n }\n\n if(forceSelection) {\n this.updateContainer(forceSelection);\n }\n }\n\n public cancelSelection = () => {\n for(const mid of this.selectedMids) {\n const mounted = this.bubbles.getMountedBubble(mid);\n if(mounted) {\n //this.toggleByBubble(mounted.message.grouped_id ? mounted.bubble.querySelector(`.grouped-item[data-mid=\"${mid}\"]`) : mounted.bubble);\n this.toggleByBubble(mounted.bubble);\n }\n /* const bubble = this.appImManager.bubbles[mid];\n if(bubble) {\n this.toggleByBubble(bubble);\n } */\n }\n\n this.selectedMids.clear();\n this.toggleSelection();\n cancelSelection();\n };\n\n public cleanup() {\n this.selectedMids.clear();\n this.toggleSelection(false);\n }\n\n private updateBubbleSelection(bubble: HTMLElement, isSelected: boolean) {\n this.toggleBubbleCheckbox(bubble, true);\n const input = this.getCheckboxInputFromBubble(bubble);\n input.checked = isSelected;\n\n this.toggleSelection();\n this.updateContainer();\n SetTransition(bubble, 'is-selected', isSelected, 200);\n }\n\n private isGroupedBubbleSelected(bubble: HTMLElement) {\n const groupedCheckboxInput = this.getCheckboxInputFromBubble(bubble);\n return groupedCheckboxInput?.checked;\n }\n\n private isGroupedMidsSelected(mid: number) {\n const mids = this.chat.getMidsByMid(mid);\n const selectedMids = mids.filter(mid => this.selectedMids.has(mid));\n return mids.length === selectedMids.length;\n }\n\n public toggleByBubble = (bubble: HTMLElement) => {\n if(!this.canSelectBubble(bubble)) return;\n\n const mid = +bubble.dataset.mid;\n\n const isGrouped = bubble.classList.contains('is-grouped');\n if(isGrouped) {\n if(!this.isGroupedBubbleSelected(bubble)) {\n const mids = this.chat.getMidsByMid(mid);\n mids.forEach(mid => this.selectedMids.delete(mid));\n }\n\n this.bubbles.getBubbleGroupedItems(bubble).forEach(this.toggleByBubble);\n return;\n }\n\n const found = this.selectedMids.has(mid);\n if(found) {\n this.selectedMids.delete(mid);\n } else {\n const diff = MAX_SELECTION_LENGTH - this.selectedMids.size - 1;\n if(diff < 0) {\n toast(I18n.format('Chat.Selection.LimitToast', true));\n return;\n /* const it = this.selectedMids.values();\n do {\n const mid = it.next().value;\n const mounted = this.appImManager.getMountedBubble(mid);\n if(mounted) {\n this.toggleByBubble(mounted.bubble);\n } else {\n const mids = this.appMessagesManager.getMidsByMid(mid);\n for(const mid of mids) {\n this.selectedMids.delete(mid);\n }\n }\n } while(this.selectedMids.size > MAX_SELECTION_LENGTH); */\n }\n\n this.selectedMids.add(mid);\n }\n\n const isGroupedItem = bubble.classList.contains('grouped-item');\n if(isGroupedItem) {\n const groupContainer = findUpClassName(bubble, 'bubble');\n const isGroupedSelected = this.isGroupedBubbleSelected(groupContainer);\n const isGroupedMidsSelected = this.isGroupedMidsSelected(mid);\n\n const willChange = isGroupedMidsSelected || isGroupedSelected;\n if(willChange) {\n this.updateBubbleSelection(groupContainer, isGroupedMidsSelected);\n }\n }\n\n this.updateBubbleSelection(bubble, !found);\n };\n\n /**\n * ! Call this method only to handle deleted messages\n */\n public deleteSelectedMids(mids: number[]) {\n mids.forEach(mid => {\n this.selectedMids.delete(mid);\n });\n\n this.updateContainer();\n this.toggleSelection();\n }\n\n public canSelectBubble(bubble: HTMLElement) {\n return !bubble.classList.contains('service') && !bubble.classList.contains('is-sending');\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type Chat from \"./chat\";\nimport type ChatTopbar from \"./topbar\";\nimport mediaSizes from \"../../helpers/mediaSizes\";\nimport { attachClickEvent, cancelEvent } from \"../../helpers/dom\";\nimport DivAndCaption from \"../divAndCaption\";\nimport { ripple } from \"../ripple\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\n\n//const classNames: string[] = [];\nconst classNames: string[] = ['is-pinned-message-shown', 'is-pinned-audio-shown'];\nconst CLASSNAME_BASE = 'pinned-container';\nconst HEIGHT = 52;\n\nexport default class PinnedContainer {\n private close: HTMLElement;\n protected wrapper: HTMLElement;\n\n constructor(protected topbar: ChatTopbar, protected chat: Chat, public listenerSetter: ListenerSetter, protected className: string, public divAndCaption: DivAndCaption<(title: string, subtitle: string, message?: any) => void>, onClose?: () => void | Promise<boolean>) {\n /* const prev = this.divAndCaption.fill;\n this.divAndCaption.fill = (mid, title, subtitle) => {\n this.divAndCaption.container.dataset.mid = '' + mid;\n prev(mid, title, subtitle);\n }; */\n\n //classNames.push(`is-pinned-${className}-shown`);\n\n divAndCaption.container.classList.add(CLASSNAME_BASE, 'hide');\n divAndCaption.title.classList.add(CLASSNAME_BASE + '-title');\n divAndCaption.subtitle.classList.add(CLASSNAME_BASE + '-subtitle');\n divAndCaption.content.classList.add(CLASSNAME_BASE + '-content');\n\n this.close = document.createElement('button');\n this.close.classList.add(CLASSNAME_BASE + '-close', `pinned-${className}-close`, 'btn-icon', 'tgico-close');\n\n //divAndCaption.container.prepend(this.close);\n\n this.wrapper = document.createElement('div');\n this.wrapper.classList.add(CLASSNAME_BASE + '-wrapper');\n this.wrapper.append(...Array.from(divAndCaption.container.children));\n ripple(this.wrapper);\n \n divAndCaption.container.append(this.close, this.wrapper);\n\n attachClickEvent(this.close, (e) => {\n cancelEvent(e);\n\n ((onClose ? onClose() : null) || Promise.resolve(true)).then(needClose => {\n if(needClose) {\n this.toggle(true);\n }\n });\n }, {listenerSetter: this.listenerSetter});\n }\n\n public toggle(hide?: boolean) {\n const isHidden = this.divAndCaption.container.classList.contains('hide');\n if(hide === undefined) {\n hide = !isHidden;\n } else if(hide === isHidden) {\n return;\n }\n\n this.divAndCaption.container.classList.toggle('is-floating', mediaSizes.isMobile);\n this.topbar.container.classList.toggle('is-pinned-floating', mediaSizes.isMobile);\n\n const scrollable = this.chat.bubbles.scrollable;\n\n const scrollTop = mediaSizes.isMobile /* && !appImManager.scrollable.isScrolledDown */ ? scrollable.scrollTop : undefined;\n this.divAndCaption.container.classList.toggle('hide', hide);\n const className = `is-pinned-${this.className}-shown`;\n this.topbar.container.classList.toggle(className, !hide);\n\n const active = classNames.filter(className => this.topbar.container.classList.contains(className));\n const maxActive = hide ? 0 : 1;\n \n if(scrollTop !== undefined && active.length <= maxActive/* && !scrollable.isScrolledDown */) {\n scrollable.scrollTop = scrollTop + ((hide ? -1 : 1) * HEIGHT);\n }\n\n this.topbar.setUtilsWidth();\n }\n\n public fill(title: string, subtitle: string, message: any) {\n this.divAndCaption.container.dataset.peerId = '' + message.peerId;\n this.divAndCaption.container.dataset.mid = '' + message.mid;\n this.divAndCaption.fill(title, subtitle, message);\n this.topbar.setUtilsWidth();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type ChatTopbar from \"./topbar\";\nimport { RichTextProcessor } from \"../../lib/richtextprocessor\";\nimport rootScope from \"../../lib/rootScope\";\nimport { attachClickEvent, cancelEvent } from \"../../helpers/dom\";\nimport appMediaPlaybackController from \"../appMediaPlaybackController\";\nimport DivAndCaption from \"../divAndCaption\";\nimport { formatDate } from \"../wrappers\";\nimport PinnedContainer from \"./pinnedContainer\";\nimport Chat from \"./chat\";\n\nexport default class ChatAudio extends PinnedContainer {\n private toggleEl: HTMLElement;\n\n constructor(protected topbar: ChatTopbar, protected chat: Chat, protected appMessagesManager: AppMessagesManager, protected appPeersManager: AppPeersManager) {\n super(topbar, chat, topbar.listenerSetter, 'audio', new DivAndCaption('pinned-audio', (title: string, subtitle: string) => {\n this.divAndCaption.title.innerHTML = title;\n this.divAndCaption.subtitle.innerHTML = subtitle;\n }), () => {\n if(this.toggleEl.classList.contains('flip-icon')) {\n appMediaPlaybackController.toggle();\n }\n });\n\n this.divAndCaption.border.remove();\n\n this.toggleEl = document.createElement('button');\n this.toggleEl.classList.add('pinned-audio-ico', 'tgico', 'btn-icon');\n attachClickEvent(this.toggleEl, (e) => {\n cancelEvent(e);\n appMediaPlaybackController.toggle();\n }, {listenerSetter: this.topbar.listenerSetter});\n\n this.wrapper.prepend(this.toggleEl);\n\n this.topbar.listenerSetter.add(rootScope, 'audio_play', (e) => {\n const {doc, mid, peerId} = e;\n\n let title: string, subtitle: string;\n const message = appMessagesManager.getMessageByPeer(peerId, mid);\n if(doc.type === 'voice' || doc.type === 'round') {\n title = appPeersManager.getPeerTitle(message.fromId, false, true);\n //subtitle = 'Voice message';\n subtitle = formatDate(message.date, false, false);\n } else {\n title = doc.audioTitle || doc.file_name;\n subtitle = doc.audioPerformer ? RichTextProcessor.wrapPlainText(doc.audioPerformer) : 'Unknown Artist';\n }\n\n this.fill(title, subtitle, message);\n this.toggleEl.classList.add('flip-icon');\n this.toggle(false);\n });\n\n this.topbar.listenerSetter.add(rootScope, 'audio_pause', () => {\n this.toggleEl.classList.remove('flip-icon');\n });\n }\n}","// https://github.com/evgeny-nadymov/telegram-react/blob/master/src/Components/ColumnMiddle/PinnedMessageBorder.js\n\nexport default class PinnedMessageBorder {\n private border: HTMLElement;\n private wrapper: HTMLElement;\n private svg: SVGSVGElement;\n private defs: SVGDefsElement;\n private clipPath: SVGClipPathElement;\n private path: SVGPathElement;\n private mark: HTMLElement;\n\n private count: number;\n private index: number;\n\n private drawRect = (x: number, y: number, width: number, height: number, radius: number) => {\n return `M${x},${y + radius}a${radius},${radius},0,0,1,${width},0v${height - 2 * radius}a${radius},${radius},0,0,1,${-width},0Z`;\n };\n\n private getClipPath = (id: string, barHeight: number, count: number) => {\n const radius = 1;\n\n let d = '';\n if(count === 3) {\n d = this.drawRect(0, 0, 2, barHeight, radius)\n + this.drawRect(0, 11, 2, barHeight + 1, radius)\n + this.drawRect(0, 23, 2, barHeight, radius);\n } else {\n for(let i = 0; i < count; i++) {\n d += this.drawRect(0, (barHeight + 2) * i, 2, barHeight, radius);\n }\n }\n\n if(!this.clipPath) {\n this.clipPath = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath');\n this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n\n this.clipPath.append(this.path);\n }\n\n this.clipPath.id = id;\n this.path.setAttributeNS(null, 'd', d);\n\n return this.clipPath;\n };\n\n private getBarHeight = (count: number, index: number) => {\n let barHeight = 32;\n if(count === 1) {\n barHeight = 32;\n } else if(count === 2) {\n barHeight = 15;\n } else if(count === 3) {\n barHeight = 9;\n } else if(count === 4) {\n barHeight = 7;\n } else if(count > 3) {\n barHeight = 7;\n }\n\n return barHeight;\n };\n\n private getMarkHeight = (count: number, index: number) => {\n let barHeight = 32;\n if(count === 1) {\n barHeight = 32;\n } else if(count === 2) {\n barHeight = 15;\n } else if(count === 3) {\n barHeight = index === 1 ? 10 : 9;\n } else if(count === 4) {\n barHeight = 7;\n } else if(count > 3) {\n barHeight = 7;\n }\n\n return barHeight;\n };\n\n private getMarkTranslateY = (index: number, barHeight: number, count: number) => {\n if(count === 1) {\n return 0;\n } else if(count === 2) {\n return index === 0 ? 0 : barHeight + 2;\n }\n\n if(count === 3) {\n if(index === 0) {\n return 0;\n } else if (index === 1) {\n return 11;\n }\n\n return 23;\n } else {\n return (barHeight + 2) * index;\n }\n };\n\n private getTrackTranslateY = (index: number, count: number, barHeight: number, trackHeight: number) => {\n if(count <= 4) {\n return 0;\n }\n\n if(index <= 1) {\n return 0;\n } else if(index >= count - 2) {\n return trackHeight - 32;\n }\n\n return (barHeight + 4) / 2 + (index - 2) * (barHeight + 2);\n };\n\n private getTrackHeight = (count: number, barHeight: number) => {\n return count <= 3 ? 32 : barHeight * count + 2 * (count - 1);\n };\n\n public render(count: number, index: number) {\n if(!this.border) {\n this.border = document.createElement('div');\n this.border.classList.add('pinned-message-border');\n\n this.wrapper = document.createElement('div');\n this.border.append(this.wrapper);\n }\n \n if(count === 1) {\n if(this.count !== count) {\n this.wrapper.className = 'pinned-message-border-wrapper-1';\n this.border.classList.remove('pinned-message-border-mask');\n this.wrapper.innerHTML = this.wrapper.style.cssText = '';\n }\n\n return this.border;\n }\n\n const barHeight = this.getBarHeight(count, index);\n const markHeight = this.getMarkHeight(count, index);\n const trackHeight = this.getTrackHeight(count, barHeight);\n\n const clipPathId = `clipPath_${count}`;\n const clipPath = this.getClipPath(clipPathId, barHeight, count);\n\n const markTranslateY = this.getMarkTranslateY(index, barHeight, count);\n const trackTranslateY = this.getTrackTranslateY(index, count, barHeight, trackHeight);\n\n this.border.classList.toggle('pinned-message-border-mask', count > 4);\n\n this.wrapper.className = 'pinned-message-border-wrapper';\n this.wrapper.style.cssText = `clip-path: url(#${clipPathId}); width: 2px; height: ${trackHeight}px; transform: translateY(-${trackTranslateY}px);`;\n \n if(!this.svg) {\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n this.svg.setAttributeNS(null, 'height', '0');\n this.svg.setAttributeNS(null, 'width', '0');\n \n this.defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n this.defs.append(clipPath);\n\n this.svg.append(this.defs);\n\n this.mark = document.createElement('div');\n this.mark.classList.add('pinned-message-border-mark');\n }\n\n if(!this.svg.parentElement) {\n this.wrapper.append(this.svg, this.mark);\n }\n\n this.mark.style.cssText = `height: ${markHeight}px; transform: translateY(${markTranslateY}px);`;\n \n this.count = count;\n this.index = index;\n\n return this.border;\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type ChatTopbar from \"./topbar\";\nimport PopupPinMessage from \"../popups/unpinMessage\";\nimport PinnedContainer from \"./pinnedContainer\";\nimport PinnedMessageBorder from \"./pinnedMessageBorder\";\nimport ReplyContainer, { wrapReplyDivAndCaption } from \"./replyContainer\";\nimport rootScope from \"../../lib/rootScope\";\nimport { attachClickEvent, cancelEvent, handleScrollSideEvent } from \"../../helpers/dom\";\nimport Chat from \"./chat\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\nimport ButtonIcon from \"../buttonIcon\";\nimport { debounce } from \"../../helpers/schedulers\";\nimport { getHeavyAnimationPromise } from \"../../hooks/useHeavyAnimationCheck\";\nimport { i18n } from \"../../lib/langPack\";\n\nclass AnimatedSuper {\n static DURATION = 200;\n static BASE_CLASS = 'animated-super';\n container: HTMLDivElement;\n rows: {[index: string]: {element: HTMLElement, timeout?: number, new?: true}} = {};\n clearTimeout: number;\n\n constructor() {\n this.container = document.createElement('div');\n this.container.className = AnimatedSuper.BASE_CLASS;\n }\n\n public getRow(index: number, animateFirst = false) {\n if(this.rows[index]) return this.rows[index].element;\n const row = document.createElement('div');\n const isFirst = !Object.keys(this.rows).length && !animateFirst;\n row.className = AnimatedSuper.BASE_CLASS + '-row' + (isFirst ? '' : ' is-hiding hide');\n this.rows[index] = {element: row, new: true};\n this.container.append(row);\n return row;\n }\n\n public clearRow(index: number) {\n if(!this.rows[index]) return;\n this.rows[index].element.remove();\n delete this.rows[index];\n }\n\n public clearRows(currentIndex?: number) {\n if(this.clearTimeout) clearTimeout(this.clearTimeout);\n this.clearTimeout = window.setTimeout(() => {\n for(const i in this.rows) {\n if(+i === currentIndex) continue;\n this.clearRow(+i);\n }\n }, AnimatedSuper.DURATION);\n }\n\n public setNewRow(index: number, reflow = false) {\n const row = this.rows[index];\n if(row.new) {\n if(reflow) {\n row.element.classList.remove('hide');\n void row.element.offsetLeft; // reflow\n } else {\n row.element.classList.remove('is-hiding', 'hide');\n }\n\n delete row.new;\n }\n\n this.clearRows(index);\n }\n\n public animate(index: number, previousIndex: number, fromTop = index > previousIndex, ignorePrevious = false) {\n if(index === previousIndex) { // * handle if set index 0 and previousIndex 0\n return this.setNewRow(index);\n }\n\n const row = this.rows[index];\n const previousRow = this.rows[previousIndex];\n if(!previousRow && !ignorePrevious) {\n return this.setNewRow(index);\n }\n\n const sides = ['from-top', 'from-bottom'];\n if(!fromTop) sides.reverse();\n\n row.element.classList.add(sides[0]);\n row.element.classList.remove(sides[1]);\n if(previousRow) {\n previousRow.element.classList.add(sides[1]);\n previousRow.element.classList.remove(sides[0]);\n }\n\n if(row.new) {\n this.setNewRow(index, true);\n }\n\n row.element.classList.toggle('is-hiding', false);\n previousRow && previousRow.element.classList.toggle('is-hiding', true);\n\n /* const height = row.element.getBoundingClientRect().height;\n row.element.style.transform = `translateY(${fromTop ? height * -1 : height}px)`;\n if(previousRow) {\n previousRow.element.style.transform = `translateY(${fromTop ? height : height * -1}px)`;\n } */\n\n /* row.element.style.setProperty('--height', row.element.getBoundingClientRect().height + 'px');\n if(previousRow) {\n previousRow.element.style.setProperty('--height', previousRow.element.getBoundingClientRect().height + 'px');\n } */\n \n this.clearRows(index);\n }\n}\n\nclass AnimatedCounter {\n static EMPTY_INDEX = -1;\n static BASE_CLASS = 'animated-counter';\n container: HTMLElement;\n decimals: {\n container: HTMLElement,\n placeholder: HTMLElement,\n animatedSuper: AnimatedSuper\n }[] = [];\n previousNumber = 0;\n clearTimeout: number;\n\n constructor(private reverse = false) {\n this.container = document.createElement('div');\n this.container.className = AnimatedCounter.BASE_CLASS;\n }\n\n getDecimal(index: number) {\n if(this.decimals[index]) return this.decimals[index];\n const item = document.createElement('div');\n item.className = AnimatedCounter.BASE_CLASS + '-decimal';\n\n const placeholder = document.createElement('div');\n placeholder.className = AnimatedCounter.BASE_CLASS + '-decimal-placeholder';\n\n const animatedSuper = new AnimatedSuper();\n animatedSuper.container.className = AnimatedCounter.BASE_CLASS + '-decimal-wrapper';\n\n item.append(placeholder, animatedSuper.container);\n\n this.container.append(item);\n\n return this.decimals[index] = {container: item, placeholder, animatedSuper};\n }\n\n clear(number: number) {\n if(this.clearTimeout) clearTimeout(this.clearTimeout);\n\n const decimals = ('' + number).length;\n if(decimals >= this.decimals.length) {\n return;\n }\n\n this.clearTimeout = window.setTimeout(() => {\n const byDecimal = this.decimals.splice(decimals, this.decimals.length - decimals);\n byDecimal.forEach((decimal) => {\n decimal.container.remove();\n });\n }, AnimatedSuper.DURATION);\n }\n\n /* prepareNumber(number: number) {\n const decimals = ('' + number).length;\n if(this.decimals.length < decimals) {\n for(let i = this.decimals.length; i < decimals; ++i) {\n this.getDecimal(i);\n }\n }\n } */\n\n hideLeft(number: number) {\n const decimals = ('' + number).length;\n const byDecimal = this.decimals.slice(decimals);//this.decimals.splice(deleteCount, this.decimals.length - deleteCount);\n byDecimal.forEach((decimal) => {\n const previousDecimalNumber = +decimal.placeholder.innerText || 0;\n const row = decimal.animatedSuper.getRow(AnimatedCounter.EMPTY_INDEX, true);\n decimal.animatedSuper.animate(AnimatedCounter.EMPTY_INDEX, previousDecimalNumber, this.reverse ? number < this.previousNumber : number > this.previousNumber, true);\n });\n\n this.clear(number);\n }\n\n setCount(number: number) {\n //this.prepareNumber(number);\n\n const previousByDecimal = Array.from('' + this.previousNumber).map(n => +n);\n const byDecimal = Array.from('' + number).map(n => +n);\n byDecimal.forEach((decimalNumber, idx) => {\n const decimal = this.getDecimal(idx);\n //const row = decimal.animatedSuper.getRow(number, true);\n const row = decimal.animatedSuper.getRow(decimalNumber, true);\n const previousDecimalNumber = previousByDecimal[idx] ?? AnimatedCounter.EMPTY_INDEX;\n row.innerText = decimal.placeholder.innerText = '' + decimalNumber;\n //decimal.animatedSuper.animate(number, this.previousNumber, this.reverse ? number < this.previousNumber : number > this.previousNumber, true);\n decimal.animatedSuper.animate(decimalNumber, previousDecimalNumber, this.reverse ? number < this.previousNumber : number > this.previousNumber, true);\n });\n\n this.hideLeft(number);\n //this.clear(number);\n this.previousNumber = number;\n }\n}\n\nexport default class ChatPinnedMessage {\n public static LOAD_COUNT = 50;\n public static LOAD_OFFSET = 5;\n\n public pinnedMessageContainer: PinnedContainer;\n public pinnedMessageBorder: PinnedMessageBorder;\n\n public pinnedMaxMid = 0;\n public pinnedMid = 0;\n public pinnedIndex = -1;\n public wasPinnedIndex = 0;\n public wasPinnedMediaIndex = 0;\n \n public locked = false;\n public waitForScrollBottom = false;\n\n public count = 0;\n public mids: number[] = [];\n public offsetIndex = 0;\n\n public loading = false;\n public loadedBottom = false;\n public loadedTop = false;\n\n public animatedSubtitle: AnimatedSuper;\n public animatedMedia: AnimatedSuper;\n public animatedCounter: AnimatedCounter;\n\n public listenerSetter: ListenerSetter;\n public scrollDownListenerSetter: ListenerSetter = null;\n\n public hidden = false;\n\n public getCurrentIndexPromise: Promise<any> = null;\n public btnOpen: HTMLButtonElement;\n \n public setPinnedMessage: () => void;\n\n private isStatic = false;\n\n private debug = false;\n \n constructor(private topbar: ChatTopbar, private chat: Chat, private appMessagesManager: AppMessagesManager, private appPeersManager: AppPeersManager) {\n this.listenerSetter = new ListenerSetter();\n\n this.pinnedMessageContainer = new PinnedContainer(topbar, chat, this.listenerSetter, 'message', new ReplyContainer('pinned-message'), async() => {\n if(appPeersManager.canPinMessage(this.topbar.peerId)) {\n new PopupPinMessage(this.topbar.peerId, this.pinnedMid, true);\n } else {\n new PopupPinMessage(this.topbar.peerId, 0, true);\n }\n\n return false;\n });\n\n this.pinnedMessageBorder = new PinnedMessageBorder();\n this.pinnedMessageContainer.divAndCaption.border.replaceWith(this.pinnedMessageBorder.render(1, 0));\n\n this.animatedSubtitle = new AnimatedSuper();\n this.pinnedMessageContainer.divAndCaption.subtitle.append(this.animatedSubtitle.container);\n\n this.animatedMedia = new AnimatedSuper();\n this.animatedMedia.container.classList.add('pinned-message-media-container');\n this.pinnedMessageContainer.divAndCaption.content.prepend(this.animatedMedia.container);\n\n this.animatedCounter = new AnimatedCounter(true);\n this.pinnedMessageContainer.divAndCaption.title.append(i18n('PinnedMessage'), ' ', this.animatedCounter.container);\n\n this.btnOpen = ButtonIcon('pinlist pinned-container-close pinned-message-pinlist', {noRipple: true});\n this.pinnedMessageContainer.divAndCaption.container.prepend(this.btnOpen);\n\n attachClickEvent(this.btnOpen, (e) => {\n cancelEvent(e);\n this.topbar.openPinned(true);\n }, {listenerSetter: this.listenerSetter});\n\n this.listenerSetter.add(rootScope, 'peer_pinned_messages', (e) => {\n const peerId = e.peerId;\n\n if(peerId === this.topbar.peerId) {\n //this.wasPinnedIndex = 0;\n //setTimeout(() => {\n if(this.hidden) {\n this.pinnedMessageContainer.toggle(this.hidden = false);\n }\n\n this.loadedTop = this.loadedBottom = false;\n this.pinnedIndex = -1;\n this.pinnedMid = 0;\n this.count = 0;\n this.mids = [];\n this.offsetIndex = 0;\n this.pinnedMaxMid = 0;\n this.setCorrectIndex(0);\n //}, 300);\n }\n });\n\n this.listenerSetter.add(rootScope, 'peer_pinned_hidden', (e) => {\n const {peerId, maxId} = e;\n\n if(peerId === this.topbar.peerId) {\n this.pinnedMessageContainer.toggle(this.hidden = true);\n }\n });\n\n // * 200 - no lags\n // * 100 - need test\n this.setPinnedMessage = debounce(() => this._setPinnedMessage(), 100, true, true);\n\n this.isStatic = this.chat.type === 'discussion';\n }\n\n public destroy() {\n this.pinnedMessageContainer.divAndCaption.container.remove();\n this.pinnedMessageContainer.toggle(true);\n this.listenerSetter.removeAll();\n this.unsetScrollDownListener(false);\n }\n\n public setCorrectIndex(lastScrollDirection?: number) {\n if(this.isStatic) return;\n //return;\n\n if(this.locked || this.hidden/* || this.chat.setPeerPromise || this.chat.bubbles.messagesQueuePromise */) {\n return;\n }\n\n if((this.loadedBottom || this.loadedTop) && !this.count) {\n return;\n }\n\n //const perf = performance.now();\n let el = this.chat.bubbles.getBubbleByPoint('bottom');\n //this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);\n if(!el) return;\n\n //return;\n\n const mid = el.dataset.mid;\n if(el && mid !== undefined) {\n //this.chat.log('[PM]: setCorrectIndex will test mid:', mid);\n this.testMid(+mid, lastScrollDirection);\n }\n }\n\n public testMid(mid: number, lastScrollDirection?: number) {\n if(this.isStatic) return;\n \n //if(lastScrollDirection !== undefined) return;\n if(this.hidden) return;\n\n //this.chat.log('[PM]: testMid', mid);\n\n let currentIndex: number = this.mids.findIndex(_mid => _mid <= mid);\n if(currentIndex !== -1 && !this.isNeededMore(currentIndex)) {\n currentIndex += this.offsetIndex;\n } else if(this.loadedTop && mid < this.mids[this.mids.length - 1]) {\n //currentIndex = 0;\n currentIndex = this.mids.length - 1 + this.offsetIndex;\n } else {\n if(!this.getCurrentIndexPromise) {\n this.getCurrentIndexPromise = this.getCurrentIndex(mid, lastScrollDirection !== undefined);\n }\n\n return;\n }\n\n //const idx = Math.max(0, this.mids.indexOf(mid));\n\n /* if(currentIndex === this.count) {\n currentIndex = 0;\n } */\n\n //this.chat.log('[PM]: testMid: pinned currentIndex', currentIndex, mid);\n\n const changed = this.pinnedIndex !== currentIndex;\n if(changed) {\n if(this.waitForScrollBottom && lastScrollDirection !== undefined) {\n if(this.pinnedIndex === 0 || this.pinnedIndex > currentIndex) { // если не скроллил вниз и пытается поставить нижний пиннед - выйти\n return;\n }\n }\n\n this.pinnedIndex = currentIndex;\n this.pinnedMid = this.mids.find(_mid => _mid <= mid) || this.mids[this.mids.length - 1];\n this.setPinnedMessage();\n }\n }\n\n private isNeededMore(currentIndex: number) {\n return (this.count > ChatPinnedMessage.LOAD_COUNT && \n (\n (!this.loadedBottom && currentIndex <= ChatPinnedMessage.LOAD_OFFSET) || \n (!this.loadedTop && (this.count - 1 - currentIndex) <= ChatPinnedMessage.LOAD_OFFSET)\n )\n );\n }\n\n private async getCurrentIndex(mid: number, correctAfter = true) {\n if(this.loading) return;\n this.loading = true;\n\n try {\n let gotRest = false;\n const promises = [\n this.appMessagesManager.getSearch({\n peerId: this.topbar.peerId, \n inputFilter: {_: 'inputMessagesFilterPinned'}, \n maxId: mid, \n limit: ChatPinnedMessage.LOAD_COUNT, \n backLimit: ChatPinnedMessage.LOAD_COUNT\n })\n .then(r => {\n gotRest = true;\n return r;\n })\n ];\n \n if(!this.pinnedMaxMid) {\n const promise = this.appMessagesManager.getPinnedMessage(this.topbar.peerId).then(p => {\n if(!p.maxId) return;\n this.pinnedMaxMid = p.maxId;\n\n if(!gotRest && correctAfter) {\n this.mids = [this.pinnedMaxMid];\n this.count = p.count;\n this.pinnedIndex = 0;\n this.pinnedMid = this.mids[0];\n this.setPinnedMessage();\n //this.pinnedMessageContainer.toggle(false);\n }\n });\n \n promises.push(promise as any);\n }\n \n const result = (await Promise.all(promises))[0];\n \n let backLimited = result.history.findIndex(message => message.mid <= mid);\n if(backLimited === -1) {\n backLimited = result.history.length;\n }/* else {\n backLimited -= 1;\n } */\n \n this.offsetIndex = result.offset_id_offset ? result.offset_id_offset - backLimited : 0;\n this.mids = result.history.map(message => message.mid).slice();\n this.count = result.count;\n\n if(!this.count) {\n this.pinnedMessageContainer.toggle(true);\n }\n \n this.loadedTop = (this.offsetIndex + this.mids.length) === this.count;\n this.loadedBottom = !this.offsetIndex;\n \n this.debug && this.chat.log('[PM]: getCurrentIndex result:', mid, result, backLimited, this.offsetIndex, this.loadedTop, this.loadedBottom);\n } catch(err) {\n this.chat.log.error('[PM]: getCurrentIndex error', err);\n }\n \n this.loading = false;\n\n if(this.locked) {\n this.testMid(mid);\n } else if(correctAfter) {\n this.setCorrectIndex(0);\n }\n\n this.getCurrentIndexPromise = null;\n //return result.offset_id_offset || 0;\n }\n\n public setScrollDownListener() {\n this.waitForScrollBottom = true;\n\n if(!this.scrollDownListenerSetter) {\n this.scrollDownListenerSetter = new ListenerSetter();\n handleScrollSideEvent(this.chat.bubbles.scrollable.container, 'bottom', () => {\n this.unsetScrollDownListener();\n }, this.scrollDownListenerSetter);\n }\n }\n\n public unsetScrollDownListener(refreshPosition = true) {\n this.waitForScrollBottom = false;\n\n if(this.scrollDownListenerSetter) {\n this.scrollDownListenerSetter.removeAll();\n this.scrollDownListenerSetter = null;\n }\n\n if(refreshPosition) {\n this.setCorrectIndex(0);\n }\n }\n\n public async handleFollowingPinnedMessage() {\n this.locked = true;\n\n this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage');\n try {\n this.setScrollDownListener();\n\n const setPeerPromise = this.chat.setPeerPromise;\n if(setPeerPromise instanceof Promise) {\n await setPeerPromise;\n }\n \n //await this.chat.bubbles.scrollable.scrollLockedPromise;\n await getHeavyAnimationPromise();\n\n if(this.getCurrentIndexPromise) {\n await this.getCurrentIndexPromise;\n }\n\n this.debug && this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');\n this.locked = false;\n\n /* // подождём, пока скролл остановится\n setTimeout(() => {\n this.chat.log('[PM]: handleFollowingPinnedMessage: unlock');\n this.locked = false;\n }, 50); */\n } catch(err) {\n this.chat.log.error('[PM]: handleFollowingPinnedMessage error:', err);\n\n this.locked = false;\n this.waitForScrollBottom = false;\n this.setCorrectIndex(0);\n }\n }\n\n public async followPinnedMessage(mid: number) {\n const message = this.chat.getMessage(mid);\n if(message && !message.deleted) {\n this.chat.setMessageId(mid);\n (this.chat.setPeerPromise || Promise.resolve()).then(() => { // * debounce fast clicker\n this.handleFollowingPinnedMessage();\n this.testMid(this.pinnedIndex >= (this.count - 1) ? this.pinnedMaxMid : mid - 1);\n });\n }\n }\n\n public _setPinnedMessage() {\n /////this.log('setting pinned message', message);\n //return;\n /* const promise: Promise<any> = this.chat.setPeerPromise || this.chat.bubbles.messagesQueuePromise || Promise.resolve();\n Promise.all([\n promise\n ]).then(() => { */\n //const mids = results[0];\n const count = this.count;\n if(count) {\n const pinnedIndex = this.pinnedIndex;\n const message = this.chat.getMessage(this.pinnedMid);\n\n //this.animatedCounter.prepareNumber(count);\n\n //setTimeout(() => {\n const isLast = pinnedIndex === 0;\n this.animatedCounter.container.classList.toggle('is-last', isLast);\n //SetTransition(this.animatedCounter.container, 'is-last', isLast, AnimatedSuper.DURATION);\n if(!isLast) {\n this.animatedCounter.setCount(count - pinnedIndex);\n }\n //}, 100);\n\n //this.pinnedMessageContainer.fill(undefined, message.message, message);\n this.pinnedMessageContainer.toggle(false);\n\n const fromTop = pinnedIndex > this.wasPinnedIndex;\n\n this.debug && this.chat.log('[PM]: setPinnedMessage: fromTop', fromTop, pinnedIndex, this.wasPinnedIndex);\n\n const writeTo = this.animatedSubtitle.getRow(pinnedIndex);\n const writeMediaTo = this.animatedMedia.getRow(pinnedIndex);\n writeMediaTo.classList.add('pinned-message-media');\n //writeMediaTo.innerHTML = writeMediaTo.style.cssText = writeMediaTo.dataset.docId = '';\n const isMediaSet = wrapReplyDivAndCaption({\n title: undefined,\n titleEl: null,\n subtitle: message.message,\n subtitleEl: writeTo,\n message,\n mediaEl: writeMediaTo\n });\n\n this.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-media', isMediaSet);\n\n //if(this.wasPinnedIndex !== this.pinnedIndex) {\n this.animatedSubtitle.animate(pinnedIndex, this.wasPinnedIndex);\n if(isMediaSet) {\n this.animatedMedia.animate(pinnedIndex, this.wasPinnedMediaIndex); // * wasPinnedMediaIndex из-за того, что блок меняется с другим алгоритмом\n this.wasPinnedMediaIndex = pinnedIndex;\n } else {\n this.animatedMedia.clearRows();\n }\n //}\n\n this.pinnedMessageBorder.render(count, count - pinnedIndex - 1);\n this.wasPinnedIndex = pinnedIndex;\n this.pinnedMessageContainer.divAndCaption.container.dataset.mid = '' + message.mid;\n } else {\n this.pinnedMessageContainer.toggle(true);\n this.wasPinnedIndex = 0;\n }\n\n this.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-many', this.count > 1);\n //});\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type ChatTopbar from \"./topbar\";\nimport { cancelEvent, whichChild } from \"../../helpers/dom\";\nimport AppSearch, { SearchGroup } from \"../appSearch\";\nimport PopupDatePicker from \"../popups/datePicker\";\nimport { ripple } from \"../ripple\";\nimport InputSearch from \"../inputSearch\";\nimport type Chat from \"./chat\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\n\nexport default class ChatSearch {\n private element: HTMLElement;\n private backBtn: HTMLElement;\n private inputSearch: InputSearch;\n\n private results: HTMLElement;\n\n private footer: HTMLElement;\n private dateBtn: HTMLElement;\n private foundCountEl: HTMLElement;\n private controls: HTMLElement;\n private downBtn: HTMLElement;\n private upBtn: HTMLElement;\n\n private appSearch: AppSearch;\n private searchGroup: SearchGroup;\n\n private foundCount = 0;\n private selectedIndex = 0;\n private setPeerPromise: Promise<any>;\n\n constructor(private topbar: ChatTopbar, private chat: Chat) {\n this.element = document.createElement('div');\n this.element.classList.add('sidebar-header', 'chat-search', 'chatlist-container');\n\n this.backBtn = document.createElement('button');\n this.backBtn.classList.add('btn-icon', 'tgico-left', 'sidebar-close-button');\n ripple(this.backBtn);\n \n this.backBtn.addEventListener('click', () => {\n this.topbar.container.classList.remove('hide-pinned');\n this.element.remove();\n this.inputSearch.remove();\n this.results.remove();\n this.footer.remove();\n this.footer.removeEventListener('click', this.onFooterClick);\n this.dateBtn.removeEventListener('click', this.onDateClick);\n this.upBtn.removeEventListener('click', this.onUpClick);\n this.downBtn.removeEventListener('click', this.onDownClick);\n this.searchGroup.list.removeEventListener('click', this.onResultsClick);\n this.chat.bubbles.bubblesContainer.classList.remove('search-results-active');\n }, {once: true});\n\n this.inputSearch = new InputSearch('Search');\n \n // Results\n this.results = document.createElement('div');\n this.results.classList.add('chat-search-results', 'chatlist-container');\n\n this.searchGroup = new SearchGroup('', 'messages', undefined, '', false);\n this.searchGroup.list.addEventListener('click', this.onResultsClick);\n\n this.appSearch = new AppSearch(this.results, this.inputSearch, {\n messages: this.searchGroup\n }, (count) => {\n this.foundCount = count;\n\n if(!this.foundCount) {\n this.foundCountEl.innerText = this.inputSearch.value ? 'No results' : '';\n this.results.classList.remove('active');\n this.chat.bubbles.bubblesContainer.classList.remove('search-results-active');\n this.upBtn.setAttribute('disabled', 'true');\n this.downBtn.setAttribute('disabled', 'true');\n } else {\n this.selectResult(this.searchGroup.list.children[0] as HTMLElement);\n }\n });\n this.appSearch.beginSearch(this.chat.peerId, this.chat.threadId);\n\n //appImManager.topbar.parentElement.insertBefore(this.results, appImManager.bubblesContainer);\n this.chat.bubbles.bubblesContainer.append(this.results);\n\n // Footer\n this.footer = document.createElement('div');\n this.footer.classList.add('chat-search-footer');\n\n this.footer.addEventListener('click', this.onFooterClick);\n ripple(this.footer);\n\n this.foundCountEl = document.createElement('span');\n this.foundCountEl.classList.add('chat-search-count');\n\n this.dateBtn = document.createElement('button');\n this.dateBtn.classList.add('btn-icon', 'tgico-calendar');\n\n this.controls = document.createElement('div');\n this.controls.classList.add('chat-search-controls');\n\n this.upBtn = document.createElement('button');\n this.upBtn.classList.add('btn-icon', 'tgico-up');\n this.downBtn = document.createElement('button');\n this.downBtn.classList.add('btn-icon', 'tgico-down');\n\n this.upBtn.setAttribute('disabled', 'true');\n this.downBtn.setAttribute('disabled', 'true');\n\n this.dateBtn.addEventListener('click', this.onDateClick);\n this.upBtn.addEventListener('click', this.onUpClick);\n this.downBtn.addEventListener('click', this.onDownClick);\n this.controls.append(this.upBtn, this.downBtn);\n\n this.footer.append(this.foundCountEl, this.dateBtn, this.controls);\n \n this.topbar.container.parentElement.insertBefore(this.footer, chat.input.chatInput);\n\n // Append container\n this.element.append(this.backBtn, this.inputSearch.container);\n\n this.topbar.container.classList.add('hide-pinned');\n this.topbar.container.parentElement.append(this.element);\n\n this.inputSearch.input.focus();\n }\n\n onDateClick = (e: MouseEvent) => {\n cancelEvent(e);\n new PopupDatePicker(new Date(), this.chat.bubbles.onDatePick).show();\n };\n\n selectResult = (elem: HTMLElement) => {\n if(this.setPeerPromise) return this.setPeerPromise;\n\n const peerId = +elem.dataset.peerId;\n const lastMsgId = +elem.dataset.mid || undefined;\n\n const index = whichChild(elem);\n\n if(index === (this.foundCount - 1)) {\n this.upBtn.setAttribute('disabled', 'true');\n } else {\n this.upBtn.removeAttribute('disabled');\n }\n\n if(!index) {\n this.downBtn.setAttribute('disabled', 'true');\n } else {\n this.downBtn.removeAttribute('disabled');\n }\n\n this.results.classList.remove('active');\n this.chat.bubbles.bubblesContainer.classList.remove('search-results-active');\n\n const res = this.chat.setPeer(peerId, lastMsgId);\n this.setPeerPromise = ((res instanceof Promise ? res : Promise.resolve(res)) as Promise<any>).then(() => {\n this.selectedIndex = index;\n this.foundCountEl.innerText = `${index + 1} of ${this.foundCount}`;\n\n const renderedCount = this.searchGroup.list.childElementCount;\n if(this.selectedIndex >= (renderedCount - 6)) {\n this.appSearch.searchMore();\n }\n }).finally(() => {\n this.setPeerPromise = null;\n });\n };\n\n onResultsClick = (e: MouseEvent) => {\n const target = findUpTag(e.target, 'LI');\n if(target) {\n this.selectResult(target);\n }\n };\n\n onFooterClick = (e: MouseEvent) => {\n if(this.foundCount) {\n this.chat.bubbles.bubblesContainer.classList.toggle('search-results-active');\n this.results.classList.toggle('active');\n }\n };\n\n onUpClick = (e: MouseEvent) => {\n cancelEvent(e);\n this.selectResult(this.searchGroup.list.children[this.selectedIndex + 1] as HTMLElement);\n };\n\n onDownClick = (e: MouseEvent) => {\n cancelEvent(e);\n this.selectResult(this.searchGroup.list.children[this.selectedIndex - 1] as HTMLElement);\n };\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appSidebarRight, { AppSidebarRight } from \"..\";\nimport AppSearch, { SearchGroup } from \"../../appSearch\";\nimport InputSearch from \"../../inputSearch\";\nimport { SliderSuperTab } from \"../../slider\";\n\nexport default class AppPrivateSearchTab extends SliderSuperTab {\n private inputSearch: InputSearch;\n private appSearch: AppSearch;\n\n private peerId = 0;\n private threadId = 0;\n\n onOpenAfterTimeout() {\n this.appSearch.beginSearch(this.peerId, this.threadId);\n }\n\n protected init() {\n this.container.id = 'search-private-container';\n this.container.classList.add('chatlist-container');\n this.inputSearch = new InputSearch('Search');\n this.title.replaceWith(this.inputSearch.container);\n\n const c = document.createElement('div');\n c.classList.add('chatlist-container');\n this.scrollable.container.replaceWith(c);\n this.appSearch = new AppSearch(c, this.inputSearch, {\n messages: new SearchGroup('Private Search', 'messages')\n });\n }\n\n open(peerId: number, threadId?: number) {\n const ret = super.open();\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n if(this.peerId !== 0) {\n this.appSearch.beginSearch(this.peerId, this.threadId);\n return ret;\n }\n\n this.peerId = peerId;\n this.threadId = threadId;\n \n appSidebarRight.toggleSidebar(true);\n return ret;\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppNotificationsManager } from \"../../lib/appManagers/appNotificationsManager\";\nimport type { AppChatsManager, Channel } from \"../../lib/appManagers/appChatsManager\";\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type { AppSidebarRight } from \"../sidebarRight\";\nimport type Chat from \"./chat\";\nimport { cancelEvent, attachClickEvent, blurActiveElement, replaceContent } from \"../../helpers/dom\";\nimport mediaSizes, { ScreenSize } from \"../../helpers/mediaSizes\";\nimport { isSafari } from \"../../helpers/userAgent\";\nimport rootScope from \"../../lib/rootScope\";\nimport AvatarElement from \"../avatar\";\nimport Button from \"../button\";\nimport ButtonIcon from \"../buttonIcon\";\nimport ButtonMenuToggle from \"../buttonMenuToggle\";\nimport ChatAudio from \"./audio\";\nimport ChatPinnedMessage from \"./pinnedMessage\";\nimport ChatSearch from \"./search\";\nimport { ButtonMenuItemOptions } from \"../buttonMenu\";\nimport ListenerSetter from \"../../helpers/listenerSetter\";\nimport appStateManager from \"../../lib/appManagers/appStateManager\";\nimport PopupDeleteDialog from \"../popups/deleteDialog\";\nimport appNavigationController from \"../appNavigationController\";\nimport { LEFT_COLUMN_ACTIVE_CLASSNAME } from \"../sidebarLeft\";\nimport AppPrivateSearchTab from \"../sidebarRight/tabs/search\";\nimport PeerTitle from \"../peerTitle\";\nimport { i18n } from \"../../lib/langPack\";\nimport findUpClassName from \"../../helpers/dom/findUpClassName\";\n\nexport default class ChatTopbar {\n container: HTMLDivElement;\n btnBack: HTMLButtonElement;\n chatInfo: HTMLDivElement;\n avatarElement: AvatarElement;\n title: HTMLDivElement;\n subtitle: HTMLDivElement;\n chatUtils: HTMLDivElement;\n btnJoin: HTMLButtonElement;\n btnPinned: HTMLButtonElement;\n btnMute: HTMLButtonElement;\n btnSearch: HTMLButtonElement;\n btnMore: HTMLButtonElement;\n \n public chatAudio: ChatAudio;\n public pinnedMessage: ChatPinnedMessage;\n\n private setUtilsRAF: number;\n public peerId: number;\n public wasPeerId: number;\n private setPeerStatusInterval: number;\n\n public listenerSetter: ListenerSetter;\n\n public menuButtons: (ButtonMenuItemOptions & {verify: () => boolean})[] = [];\n\n constructor(private chat: Chat, private appSidebarRight: AppSidebarRight, private appMessagesManager: AppMessagesManager, private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager, private appNotificationsManager: AppNotificationsManager) {\n this.listenerSetter = new ListenerSetter();\n }\n\n public construct() {\n //this.chat.log.error('Topbar construction');\n\n this.container = document.createElement('div');\n this.container.classList.add('sidebar-header', 'topbar');\n\n this.btnBack = ButtonIcon('left sidebar-close-button', {noRipple: true});\n\n // * chat info section\n this.chatInfo = document.createElement('div');\n this.chatInfo.classList.add('chat-info');\n\n const person = document.createElement('div');\n person.classList.add('person');\n\n const content = document.createElement('div');\n content.classList.add('content');\n\n const top = document.createElement('div');\n top.classList.add('top');\n\n this.title = document.createElement('div');\n this.title.classList.add('user-title');\n\n top.append(this.title);\n\n const bottom = document.createElement('div');\n bottom.classList.add('bottom');\n\n if(this.subtitle) {\n bottom.append(this.subtitle);\n }\n\n content.append(top, bottom);\n if(this.avatarElement) {\n person.append(this.avatarElement);\n }\n\n person.append(content);\n this.chatInfo.append(person);\n\n // * chat utils section\n this.chatUtils = document.createElement('div');\n this.chatUtils.classList.add('chat-utils');\n\n this.chatAudio = new ChatAudio(this, this.chat, this.appMessagesManager, this.appPeersManager);\n\n if(this.menuButtons.length) {\n this.btnMore = ButtonMenuToggle({listenerSetter: this.listenerSetter}, 'bottom-left', this.menuButtons, (e) => {\n cancelEvent(e);\n this.menuButtons.forEach(button => {\n button.element.classList.toggle('hide', !button.verify());\n });\n\n // delete button\n this.menuButtons[this.menuButtons.length - 1].element.lastChild.replaceWith(i18n(this.appPeersManager.getDeleteButtonText(this.peerId)));\n });\n }\n\n this.chatUtils.append(...[this.chatAudio ? this.chatAudio.divAndCaption.container : null, this.pinnedMessage ? this.pinnedMessage.pinnedMessageContainer.divAndCaption.container : null, this.btnJoin, this.btnPinned, this.btnMute, this.btnSearch, this.btnMore].filter(Boolean));\n\n this.container.append(this.btnBack, this.chatInfo, this.chatUtils);\n\n // * construction end\n\n // * fix topbar overflow section\n\n this.listenerSetter.add(window, 'resize', this.onResize);\n mediaSizes.addEventListener('changeScreen', this.onChangeScreen);\n\n attachClickEvent(this.container, (e) => {\n const container: HTMLElement = findUpClassName(e.target, 'pinned-container');\n blurActiveElement();\n if(container) {\n cancelEvent(e);\n \n const mid = +container.dataset.mid;\n const peerId = +container.dataset.peerId;\n if(container.classList.contains('pinned-message')) {\n //if(!this.pinnedMessage.locked) {\n this.pinnedMessage.followPinnedMessage(mid);\n //}\n } else {\n this.chat.appImManager.setInnerPeer(peerId, mid);\n }\n } else {\n if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {\n onBtnBackClick();\n } else {\n this.appSidebarRight.toggleSidebar(true);\n }\n }\n }, {listenerSetter: this.listenerSetter});\n\n const onBtnBackClick = (e?: Event) => {\n if(e) {\n cancelEvent(e);\n }\n\n //const item = appNavigationController.findItemByType('chat');\n // * return manually to chat by arrow, since can't get back to\n if(mediaSizes.activeScreen === ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {\n this.chat.appImManager.setPeer(this.peerId);\n } else {\n const isFirstChat = this.chat.appImManager.chats.indexOf(this.chat) === 0;\n appNavigationController.back(isFirstChat ? 'im' : 'chat');\n return;\n\n if(mediaSizes.activeScreen === ScreenSize.medium && !appNavigationController.findItemByType('chat')) {\n this.chat.appImManager.setPeer(0);\n blurActiveElement();\n } else {\n appNavigationController.back('chat');\n }\n }\n };\n\n attachClickEvent(this.btnBack, onBtnBackClick, {listenerSetter: this.listenerSetter});\n }\n\n public constructUtils() {\n this.menuButtons = [{\n icon: 'search',\n text: 'Search',\n onClick: () => {\n new ChatSearch(this, this.chat);\n },\n verify: () => mediaSizes.isMobile\n }, /* {\n icon: 'pinlist',\n text: 'Pinned Messages',\n onClick: () => this.openPinned(false),\n verify: () => mediaSizes.isMobile\n }, */ {\n icon: 'mute',\n text: 'ChatList.Context.Mute',\n onClick: () => {\n this.appMessagesManager.mutePeer(this.peerId);\n },\n verify: () => this.chat.type === 'chat' && rootScope.myId !== this.peerId && !this.appNotificationsManager.isPeerLocalMuted(this.peerId, false)\n }, {\n icon: 'unmute',\n text: 'ChatList.Context.Unmute',\n onClick: () => {\n this.appMessagesManager.mutePeer(this.peerId);\n },\n verify: () => this.chat.type === 'chat' && rootScope.myId !== this.peerId && this.appNotificationsManager.isPeerLocalMuted(this.peerId, false)\n }, {\n icon: 'select',\n text: 'Chat.Menu.SelectMessages',\n onClick: () => {\n this.chat.selection.toggleSelection(true, true);\n },\n verify: () => !this.chat.selection.isSelecting && !!Object.keys(this.chat.bubbles.bubbles).length\n }, {\n icon: 'select',\n text: 'Chat.Menu.ClearSelection',\n onClick: () => {\n this.chat.selection.cancelSelection();\n },\n verify: () => this.chat.selection.isSelecting\n }, {\n icon: 'delete danger',\n text: 'Delete',\n onClick: () => {\n new PopupDeleteDialog(this.peerId);\n },\n verify: () => this.chat.type === 'chat' && !!this.appMessagesManager.getDialogByPeerId(this.peerId)[0]\n }];\n\n this.btnSearch = ButtonIcon('search');\n attachClickEvent(this.btnSearch, (e) => {\n cancelEvent(e);\n if(this.peerId) {\n let tab = this.appSidebarRight.getTab(AppPrivateSearchTab);\n if(!tab) {\n tab = new AppPrivateSearchTab(this.appSidebarRight);\n }\n\n tab.open(this.peerId, this.chat.threadId);\n }\n }, {listenerSetter: this.listenerSetter});\n }\n\n public constructPeerHelpers() {\n this.avatarElement = new AvatarElement();\n this.avatarElement.setAttribute('dialog', '1');\n //this.avatarElement.setAttribute('clickable', '');\n this.avatarElement.classList.add('avatar-42', 'person-avatar');\n\n this.subtitle = document.createElement('div');\n this.subtitle.classList.add('info');\n\n this.pinnedMessage = new ChatPinnedMessage(this, this.chat, this.appMessagesManager, this.appPeersManager);\n\n this.btnJoin = Button('btn-primary btn-color-primary chat-join hide');\n this.btnJoin.append(i18n('Chat.Subscribe'));\n\n this.btnPinned = ButtonIcon('pinlist');\n this.btnMute = ButtonIcon('mute');\n\n attachClickEvent(this.btnPinned, (e) => {\n cancelEvent(e);\n blurActiveElement();\n this.openPinned(true);\n }, {listenerSetter: this.listenerSetter});\n\n attachClickEvent(this.btnMute, (e) => {\n cancelEvent(e);\n blurActiveElement();\n this.appMessagesManager.mutePeer(this.peerId);\n }, {listenerSetter: this.listenerSetter});\n\n attachClickEvent(this.btnJoin, (e) => {\n cancelEvent(e);\n\n blurActiveElement();\n this.btnJoin.setAttribute('disabled', 'true');\n this.appChatsManager.joinChannel(-this.peerId).finally(() => {\n this.btnJoin.removeAttribute('disabled');\n });\n //});\n }, {listenerSetter: this.listenerSetter});\n\n this.listenerSetter.add(rootScope, 'chat_update', (e) => {\n const peerId: number = e;\n if(this.peerId === -peerId) {\n const chat = this.appChatsManager.getChat(peerId) as Channel/* | Chat */;\n \n this.btnJoin.classList.toggle('hide', !(chat as Channel)?.pFlags?.left);\n this.setUtilsWidth();\n }\n });\n\n this.listenerSetter.add(rootScope, 'dialog_notify_settings', (dialog) => {\n if(dialog.peerId === this.peerId) {\n this.setMutedState();\n }\n });\n\n this.listenerSetter.add(rootScope, 'peer_typings', (e) => {\n const {peerId} = e;\n\n if(this.peerId === peerId) {\n this.setPeerStatus();\n }\n });\n\n this.listenerSetter.add(rootScope, 'user_update', (e) => {\n const userId = e;\n\n if(this.peerId === userId) {\n this.setPeerStatus();\n }\n });\n\n if(this.pinnedMessage) {\n this.chat.addEventListener('setPeer', (mid, isTopMessage) => {\n const middleware = this.chat.bubbles.getMiddleware();\n appStateManager.getState().then((state) => {\n if(!middleware()) return;\n \n this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[this.chat.peerId];\n \n if(isTopMessage) {\n this.pinnedMessage.unsetScrollDownListener();\n this.pinnedMessage.testMid(mid, 0); // * because slider will not let get bubble by document.elementFromPoint\n } else if(!this.pinnedMessage.locked) {\n this.pinnedMessage.handleFollowingPinnedMessage();\n this.pinnedMessage.testMid(mid);\n }\n });\n });\n }\n\n this.setPeerStatusInterval = window.setInterval(this.setPeerStatus, 60e3);\n\n return this;\n }\n\n public constructPinnedHelpers() {\n this.listenerSetter.add(rootScope, 'peer_pinned_messages', (e) => {\n const {peerId, mids, pinned} = e;\n\n if(peerId !== this.peerId) return;\n\n if(mids) {\n this.setTitle();\n }\n });\n }\n \n public constructDiscussionHelpers() {\n this.pinnedMessage = new ChatPinnedMessage(this, this.chat, this.appMessagesManager, this.appPeersManager);\n }\n\n public openPinned(byCurrent: boolean) {\n this.chat.appImManager.setInnerPeer(this.peerId, byCurrent ? +this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.dataset.mid : 0, 'pinned');\n }\n\n private onResize = () => {\n this.setUtilsWidth(true);\n };\n\n private onChangeScreen = (from: ScreenSize, to: ScreenSize) => {\n this.container.classList.toggle('is-pinned-floating', mediaSizes.isMobile);\n this.chatAudio && this.chatAudio.divAndCaption.container.classList.toggle('is-floating', to === ScreenSize.mobile);\n this.pinnedMessage && this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.classList.toggle('is-floating', to === ScreenSize.mobile);\n this.setUtilsWidth(true);\n };\n\n public destroy() {\n //this.chat.log.error('Topbar destroying');\n\n this.listenerSetter.removeAll();\n mediaSizes.removeEventListener('changeScreen', this.onChangeScreen);\n window.clearInterval(this.setPeerStatusInterval);\n \n if(this.pinnedMessage) {\n this.pinnedMessage.destroy(); // * возможно это можно не делать\n }\n\n delete this.chatAudio;\n delete this.pinnedMessage;\n }\n\n public setPeer(peerId: number) {\n this.wasPeerId = this.peerId;\n this.peerId = peerId;\n\n this.container.style.display = peerId ? '' : 'none';\n }\n\n public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number) {\n const peerId = this.peerId;\n\n if(this.avatarElement) {\n this.avatarElement.setAttribute('peer', '' + peerId);\n this.avatarElement.update();\n }\n\n const isBroadcast = this.appPeersManager.isBroadcast(peerId);\n\n this.btnMute && this.btnMute.classList.toggle('hide', !isBroadcast);\n this.btnJoin && this.btnJoin.classList.toggle('hide', !this.appChatsManager.getChat(-peerId)?.pFlags?.left);\n this.setUtilsWidth();\n\n const middleware = this.chat.bubbles.getMiddleware();\n if(this.pinnedMessage) { // * replace with new one\n if(this.chat.type === 'chat') {\n if(this.wasPeerId) { // * change\n const newPinnedMessage = new ChatPinnedMessage(this, this.chat, this.appMessagesManager, this.appPeersManager);\n this.pinnedMessage.pinnedMessageContainer.divAndCaption.container.replaceWith(newPinnedMessage.pinnedMessageContainer.divAndCaption.container);\n this.pinnedMessage.destroy();\n //this.pinnedMessage.pinnedMessageContainer.toggle(true);\n this.pinnedMessage = newPinnedMessage;\n }\n \n appStateManager.getState().then((state) => {\n if(!middleware()) return;\n \n this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[peerId];\n \n if(!isTarget) {\n this.pinnedMessage.setCorrectIndex(0);\n }\n });\n } else if(this.chat.type === 'discussion') {\n this.pinnedMessage.pinnedMid = this.chat.threadId;\n this.pinnedMessage.count = 1;\n this.pinnedMessage.pinnedIndex = 0;\n this.pinnedMessage._setPinnedMessage();\n }\n }\n\n window.requestAnimationFrame(() => {\n this.setTitle();\n this.setPeerStatus(true);\n this.setMutedState();\n });\n }\n\n public setTitle(count?: number) {\n let titleEl: HTMLElement;\n if(this.chat.type === 'pinned') {\n if(count === undefined) titleEl = i18n('Loading');\n else titleEl = i18n('PinnedMessagesCount', [count]);\n\n if(count === undefined) {\n this.appMessagesManager.getSearchCounters(this.peerId, [{_: 'inputMessagesFilterPinned'}], false).then(result => {\n const count = result[0].count;\n this.setTitle(count);\n\n // ! костыль х2, это нужно делать в другом месте\n if(!count) {\n this.chat.appImManager.setPeer(0); // * close tab\n\n // ! костыль, это скроет закреплённые сообщения сразу, вместо того, чтобы ждать пока анимация перехода закончится\n const originalChat = this.chat.appImManager.chat;\n if(originalChat.topbar.pinnedMessage) {\n originalChat.topbar.pinnedMessage.pinnedMessageContainer.toggle(true);\n }\n }\n });\n }\n } else if(this.chat.type === 'scheduled') {\n if(this.peerId === rootScope.myId) {\n //title = [count > 1 ? count : false, 'Reminders'].filter(Boolean).join(' ');\n titleEl = i18n('Reminders');\n } else {\n titleEl = i18n('ScheduledMessages');\n //title = [count > 1 ? count : false, 'Scheduled Messages'].filter(Boolean).join(' ');\n }\n \n if(count === undefined) {\n this.appMessagesManager.getScheduledMessages(this.peerId).then(mids => {\n this.setTitle(mids.length);\n });\n }\n } else if(this.chat.type === 'discussion') {\n if(count === undefined) titleEl = i18n('Loading');\n else titleEl = i18n('Chat.Title.Comments', [count]);\n\n if(count === undefined) {\n Promise.all([\n this.appMessagesManager.getHistory(this.peerId, 0, 1, 0, this.chat.threadId),\n Promise.resolve()\n ]).then(() => {\n const count = this.appMessagesManager.getHistoryStorage(this.peerId, this.chat.threadId).count;\n if(count === null) {\n setTimeout(() => {\n this.setTitle();\n }, 30);\n } else {\n this.setTitle(count);\n }\n });\n }\n } else if(this.chat.type === 'chat') {\n titleEl = new PeerTitle({\n peerId: this.peerId,\n dialog: true,\n }).element;\n }\n \n this.title.textContent = '';\n this.title.append(titleEl);\n }\n\n public setMutedState() {\n if(!this.btnMute) return;\n\n const peerId = this.peerId;\n let muted = this.appNotificationsManager.isPeerLocalMuted(peerId, false);\n if(this.appPeersManager.isBroadcast(peerId)) { // not human\n this.btnMute.classList.remove('tgico-mute', 'tgico-unmute');\n this.btnMute.classList.add(muted ? 'tgico-unmute' : 'tgico-mute');\n this.btnMute.style.display = '';\n } else {\n this.btnMute.style.display = 'none';\n }\n }\n\n // ! У МЕНЯ ПРОСТО СГОРЕЛО, САФАРИ КОНЧЕННЫЙ БРАУЗЕР - ЕСЛИ НЕ СКРЫВАТЬ БЛОК, ТО ПРИ ПЕРЕВОРОТЕ ЭКРАНА НА АЙФОНЕ БЛОК БУДЕТ НЕПРАВИЛЬНО ШИРИНЫ, ДАЖЕ БЕЗ ЭТОЙ ФУНКЦИИ!\n public setUtilsWidth = (resize = false) => {\n //return;\n if(this.setUtilsRAF) window.cancelAnimationFrame(this.setUtilsRAF);\n\n if(isSafari && resize) {\n this.chatUtils.classList.add('hide');\n }\n\n //mutationObserver.disconnect();\n this.setUtilsRAF = window.requestAnimationFrame(() => {\n \n //mutationRAF = window.requestAnimationFrame(() => {\n \n //setTimeout(() => {\n if(isSafari && resize) {\n this.chatUtils.classList.remove('hide');\n }\n /* this.chatInfo.style.removeProperty('--utils-width');\n void this.chatInfo.offsetLeft; // reflow */\n const width = /* chatUtils.scrollWidth */this.chatUtils.getBoundingClientRect().width;\n this.chat.log('utils width:', width);\n this.chatInfo.style.setProperty('--utils-width', width + 'px');\n //this.chatInfo.classList.toggle('have-utils-width', !!width);\n //}, 0);\n \n this.setUtilsRAF = 0;\n\n //mutationObserver.observe(chatUtils, observeOptions);\n //});\n });\n };\n\n public setPeerStatus = (needClear = false) => {\n if(!this.subtitle) return;\n\n const peerId = this.peerId;\n this.chat.appImManager.setPeerStatus(this.peerId, this.subtitle, needClear, false, () => peerId === this.peerId);\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppNotificationsManager } from \"../../lib/appManagers/appNotificationsManager\";\nimport type { AppChatsManager } from \"../../lib/appManagers/appChatsManager\";\nimport type { AppDocsManager } from \"../../lib/appManagers/appDocsManager\";\nimport type { AppImManager } from \"../../lib/appManagers/appImManager\";\nimport type { AppInlineBotsManager } from \"../../lib/appManagers/appInlineBotsManager\";\nimport type { AppMessagesManager } from \"../../lib/appManagers/appMessagesManager\";\nimport type { AppPeersManager } from \"../../lib/appManagers/appPeersManager\";\nimport type { AppPhotosManager } from \"../../lib/appManagers/appPhotosManager\";\nimport type { AppPollsManager } from \"../../lib/appManagers/appPollsManager\";\nimport type { AppProfileManager } from \"../../lib/appManagers/appProfileManager\";\nimport type { AppStickersManager } from \"../../lib/appManagers/appStickersManager\";\nimport type { AppUsersManager } from \"../../lib/appManagers/appUsersManager\";\nimport type { AppWebPagesManager } from \"../../lib/appManagers/appWebPagesManager\";\nimport type { ApiManagerProxy } from \"../../lib/mtproto/mtprotoworker\";\nimport type { AppDraftsManager } from \"../../lib/appManagers/appDraftsManager\";\nimport type { ServerTimeManager } from \"../../lib/mtproto/serverTimeManager\";\nimport type sessionStorage from '../../lib/sessionStorage';\nimport EventListenerBase from \"../../helpers/eventListenerBase\";\nimport { logger, LogLevels } from \"../../lib/logger\";\nimport rootScope from \"../../lib/rootScope\";\nimport appSidebarRight from \"../sidebarRight\";\nimport ChatBubbles from \"./bubbles\";\nimport ChatContextMenu from \"./contextMenu\";\nimport ChatInput from \"./input\";\nimport ChatSelection from \"./selection\";\nimport ChatTopbar from \"./topbar\";\nimport { REPLIES_PEER_ID } from \"../../lib/mtproto/mtproto_config\";\nimport SetTransition from \"../singleTransition\";\nimport { fastRaf } from \"../../helpers/schedulers\";\nimport AppPrivateSearchTab from \"../sidebarRight/tabs/search\";\nimport type { State } from \"../../lib/appManagers/appStateManager\";\nimport renderImageFromUrl from \"../../helpers/dom/renderImageFromUrl\";\n\nexport type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';\n\nexport default class Chat extends EventListenerBase<{\n setPeer: (mid: number, isTopMessage: boolean) => void\n}> {\n public container: HTMLElement;\n public backgroundEl: HTMLElement;\n\n public topbar: ChatTopbar;\n public bubbles: ChatBubbles;\n public input: ChatInput;\n public selection: ChatSelection;\n public contextMenu: ChatContextMenu;\n\n public wasAlreadyUsed = false;\n public initPeerId = 0;\n public peerId = 0;\n public threadId: number;\n public setPeerPromise: Promise<void>;\n public peerChanged: boolean;\n\n public log: ReturnType<typeof logger>;\n\n public type: ChatType = 'chat';\n\n public noAutoDownloadMedia: boolean;\n \n constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy, public appDraftsManager: AppDraftsManager, public serverTimeManager: ServerTimeManager, public storage: typeof sessionStorage, public appNotificationsManager: AppNotificationsManager) {\n super();\n\n this.container = document.createElement('div');\n this.container.classList.add('chat');\n\n this.backgroundEl = document.createElement('div');\n this.backgroundEl.classList.add('chat-background');\n\n // * constructor end\n\n this.log = logger('CHAT', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);\n //this.log.error('Chat construction');\n\n this.container.append(this.backgroundEl);\n this.appImManager.chatsContainer.append(this.container);\n }\n\n public setBackground(url: string): Promise<void> {\n const theme = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme);\n\n let item: HTMLElement;\n if(theme.background.type === 'color' && document.documentElement.style.cursor === 'grabbing') {\n const _item = this.backgroundEl.lastElementChild as HTMLElement;\n if(_item && _item.dataset.type === theme.background.type) {\n item = _item;\n }\n }\n \n if(!item) {\n item = document.createElement('div');\n item.classList.add('chat-background-item');\n item.dataset.type = theme.background.type;\n }\n\n if(theme.background.type === 'color') {\n item.style.backgroundColor = theme.background.color;\n item.style.backgroundImage = 'none';\n }\n\n return new Promise<void>((resolve) => {\n const cb = () => {\n const prev = this.backgroundEl.lastElementChild as HTMLElement;\n\n if(prev === item) {\n resolve();\n return;\n }\n\n this.backgroundEl.append(item);\n\n // * одного недостаточно, при обновлении страницы все равно фон появляется неплавно\n // ! с requestAnimationFrame лучше, но все равно иногда моргает, так что использую два фаста.\n fastRaf(() => {\n fastRaf(() => {\n SetTransition(item, 'is-visible', true, 200, prev ? () => {\n prev.remove();\n } : null);\n });\n });\n\n resolve();\n };\n\n if(url) {\n renderImageFromUrl(item, url, cb);\n } else {\n cb();\n }\n });\n }\n\n public setType(type: ChatType) {\n this.type = type;\n\n if(this.type === 'scheduled') {\n this.getMessagesStorage = () => this.appMessagesManager.getScheduledMessagesStorage(this.peerId);\n //this.getMessage = (mid) => this.appMessagesManager.getMessageFromStorage(this.appMessagesManager.getScheduledMessagesStorage(this.peerId), mid);\n }\n }\n\n public init(peerId: number) {\n this.initPeerId = peerId;\n\n this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager, this.appNotificationsManager);\n this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager, this.storage);\n this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager, this.appNotificationsManager);\n this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager);\n this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);\n\n if(this.type === 'chat') {\n this.topbar.constructUtils();\n this.topbar.constructPeerHelpers();\n } else if(this.type === 'pinned') {\n this.topbar.constructPinnedHelpers();\n } else if(this.type === 'discussion') {\n this.topbar.constructUtils();\n this.topbar.constructDiscussionHelpers();\n }\n\n this.topbar.construct();\n this.input.construct();\n\n if(this.type === 'chat') { // * гений в деле, разный порядок из-за разной последовательности действий\n this.bubbles.constructPeerHelpers();\n this.input.constructPeerHelpers();\n } else if(this.type === 'pinned') {\n this.bubbles.constructPinnedHelpers();\n this.input.constructPinnedHelpers();\n } else if(this.type === 'scheduled') {\n this.bubbles.constructScheduledHelpers();\n this.input.constructPeerHelpers();\n } else if(this.type === 'discussion') {\n this.bubbles.constructPeerHelpers();\n this.input.constructPeerHelpers();\n }\n\n this.container.classList.add('type-' + this.type);\n this.container.append(this.topbar.container, this.bubbles.bubblesContainer, this.input.chatInput);\n\n this.bubbles.listenerSetter.add(rootScope, 'dialog_migrate', ({migrateFrom, migrateTo}) => {\n if(this.peerId === migrateFrom) {\n this.setPeer(migrateTo);\n }\n });\n\n this.bubbles.listenerSetter.add(rootScope, 'dialog_drop', (e) => {\n if(e.peerId === this.peerId) {\n this.appImManager.setPeer(0);\n }\n });\n }\n\n public destroy() {\n //const perf = performance.now();\n\n this.topbar.destroy();\n this.bubbles.destroy();\n this.input.destroy();\n\n delete this.topbar;\n delete this.bubbles;\n delete this.input;\n delete this.selection;\n delete this.contextMenu;\n\n this.container.remove();\n\n //this.log.error('Chat destroy time:', performance.now() - perf);\n }\n\n public cleanup(helperToo = true) {\n this.input.cleanup(helperToo);\n this.selection.cleanup();\n }\n\n public setPeer(peerId: number, lastMsgId?: number) {\n if(this.init) {\n this.init(peerId);\n this.init = null;\n }\n\n const samePeer = this.peerId === peerId;\n if(!samePeer) {\n rootScope.broadcast('peer_changing', this);\n this.peerId = peerId;\n } else if(this.setPeerPromise) {\n return;\n }\n\n //console.time('appImManager setPeer');\n //console.time('appImManager setPeer pre promise');\n ////console.time('appImManager: pre render start');\n if(!peerId) {\n appSidebarRight.toggleSidebar(false);\n this.cleanup(true);\n this.topbar.setPeer(peerId);\n this.bubbles.setPeer(peerId);\n rootScope.broadcast('peer_changed', peerId);\n\n return;\n }\n\n // set new\n if(!samePeer) {\n const searchTab = appSidebarRight.getTab(AppPrivateSearchTab);\n if(searchTab) {\n searchTab.close();\n }\n\n appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId);\n this.input.clearHelper(); // костыль\n this.selection.cleanup(); // TODO: REFACTOR !!!!!!\n this.setAutoDownloadMedia();\n }\n\n this.peerChanged = samePeer;\n\n const result = this.bubbles.setPeer(peerId, lastMsgId);\n if(!result) {\n return;\n }\n\n const {promise} = result;\n\n //console.timeEnd('appImManager setPeer pre promise');\n \n const setPeerPromise = this.setPeerPromise = promise.finally(() => {\n if(this.setPeerPromise === setPeerPromise) {\n this.setPeerPromise = null;\n }\n });\n\n if(!samePeer) {\n appSidebarRight.sharedMediaTab.setLoadMutex(this.setPeerPromise);\n appSidebarRight.sharedMediaTab.loadSidebarMedia(true);\n }\n /* this.setPeerPromise.then(() => {\n appSidebarRight.sharedMediaTab.loadSidebarMedia(false);\n }); */\n\n return result;\n }\n\n public setAutoDownloadMedia() {\n let type: keyof State['settings']['autoDownload'];\n if(this.peerId < 0) {\n if(this.appPeersManager.isBroadcast(this.peerId)) {\n type = 'channels';\n } else {\n type = 'groups';\n }\n } else {\n if(this.appUsersManager.isContact(this.peerId)) {\n type = 'contacts';\n } else {\n type = 'private';\n }\n }\n\n this.noAutoDownloadMedia = !rootScope.settings.autoDownload[type];\n }\n\n public setMessageId(messageId?: number) {\n return this.setPeer(this.peerId, messageId);\n }\n\n public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number) {\n if(this.peerChanged) return;\n\n let peerId = this.peerId;\n this.peerChanged = true;\n\n this.cleanup(false);\n\n this.topbar.setPeer(peerId);\n this.topbar.finishPeerChange(isTarget, isJump, lastMsgId);\n this.bubbles.finishPeerChange();\n this.input.finishPeerChange();\n\n appSidebarRight.sharedMediaTab.fillProfileElements();\n\n this.log.setPrefix('CHAT-' + peerId + '-' + this.type);\n\n rootScope.broadcast('peer_changed', peerId);\n this.wasAlreadyUsed = true;\n }\n\n public getMessagesStorage() {\n return this.appMessagesManager.getMessagesStorage(this.peerId);\n }\n\n public getMessage(mid: number) {\n return this.appMessagesManager.getMessageFromStorage(this.getMessagesStorage(), mid);\n //return this.appMessagesManager.getMessageByPeer(this.peerId, mid);\n }\n\n public getMidsByMid(mid: number) {\n return this.appMessagesManager.getMidsByMessage(this.getMessage(mid));\n }\n\n public isAnyGroup() {\n return this.peerId === rootScope.myId || this.peerId === REPLIES_PEER_ID || this.appPeersManager.isAnyGroup(this.peerId);\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { AppImManager } from \"../../lib/appManagers/appImManager\";\nimport { MarkdownType, cancelEvent, getSelectedNodes, markdownTags, attachClickEvent, isSelectionEmpty } from \"../../helpers/dom\";\nimport RichTextProcessor from \"../../lib/richtextprocessor\";\nimport ButtonIcon from \"../buttonIcon\";\nimport { clamp } from \"../../helpers/number\";\nimport { isTouchSupported } from \"../../helpers/touchSupport\";\nimport { isApple, isMobile } from \"../../helpers/userAgent\";\nimport appNavigationController from \"../appNavigationController\";\nimport { _i18n } from \"../../lib/langPack\";\n//import { logger } from \"../../lib/logger\";\n\nexport default class MarkupTooltip {\n public container: HTMLElement;\n private wrapper: HTMLElement;\n private buttons: {[type in MarkdownType]: HTMLElement} = {} as any;\n private linkBackButton: HTMLElement;\n private linkApplyButton: HTMLButtonElement;\n private hideTimeout: number;\n private addedListener = false;\n private waitingForMouseUp = false;\n private linkInput: HTMLInputElement;\n private savedRange: Range;\n private mouseUpCounter: number = 0;\n //private log: ReturnType<typeof logger>;\n\n constructor(private appImManager: AppImManager) {\n //this.log = logger('MARKUP');\n }\n\n private init() {\n this.container = document.createElement('div');\n this.container.classList.add('markup-tooltip', 'z-depth-1', 'hide');\n\n this.wrapper = document.createElement('div');\n this.wrapper.classList.add('markup-tooltip-wrapper');\n \n const tools1 = document.createElement('div');\n const tools2 = document.createElement('div');\n tools1.classList.add('markup-tooltip-tools');\n tools2.classList.add('markup-tooltip-tools');\n\n const arr = ['bold', 'italic', 'underline', 'strikethrough', 'monospace', 'link'] as (keyof MarkupTooltip['buttons'])[];\n arr.forEach(c => {\n const button = ButtonIcon(c, {noRipple: true});\n tools1.append(this.buttons[c] = button);\n\n if(c !== 'link') {\n button.addEventListener('mousedown', (e) => {\n cancelEvent(e); \n this.appImManager.chat.input.applyMarkdown(c);\n this.cancelClosening();\n \n /* this.mouseUpCounter = 0;\n this.setMouseUpEvent(); */\n //this.hide();\n });\n } else {\n attachClickEvent(button, (e) => {\n cancelEvent(e);\n this.showLinkEditor();\n this.cancelClosening();\n });\n }\n });\n\n this.linkBackButton = ButtonIcon('left', {noRipple: true});\n this.linkInput = document.createElement('input');\n _i18n(this.linkInput, 'MarkupTooltip.LinkPlaceholder', undefined, 'placeholder');\n this.linkInput.classList.add('input-clear');\n this.linkInput.addEventListener('keydown', (e) => {\n const valid = !this.linkInput.value.length || !!RichTextProcessor.matchUrl(this.linkInput.value);///^(http)|(https):\\/\\//i.test(this.linkInput.value);\n\n if(e.code === 'Enter') {\n if(!valid) {\n if(this.linkInput.classList.contains('error')) {\n this.linkInput.classList.remove('error');\n void this.linkInput.offsetLeft; // reflow\n }\n\n this.linkInput.classList.add('error');\n } else {\n this.applyLink(e);\n }\n }\n });\n\n this.linkInput.addEventListener('input', (e) => {\n const valid = this.isLinkValid();\n\n this.linkInput.classList.toggle('is-valid', valid);\n this.linkInput.classList.remove('error');\n });\n\n this.linkBackButton.addEventListener('mousedown', (e) => {\n //this.log('linkBackButton click');\n cancelEvent(e);\n this.container.classList.remove('is-link');\n //input.value = '';\n this.resetSelection();\n this.setTooltipPosition();\n this.cancelClosening();\n });\n\n this.linkApplyButton = ButtonIcon('check markup-tooltip-link-apply', {noRipple: true});\n this.linkApplyButton.addEventListener('mousedown', (e) => {\n //this.log('linkApplyButton click');\n this.applyLink(e);\n });\n\n const applyDiv = document.createElement('div');\n applyDiv.classList.add('markup-tooltip-link-apply-container');\n \n const delimiter1 = document.createElement('span');\n const delimiter2 = document.createElement('span');\n const delimiter3 = document.createElement('span');\n delimiter1.classList.add('markup-tooltip-delimiter');\n delimiter2.classList.add('markup-tooltip-delimiter');\n delimiter3.classList.add('markup-tooltip-delimiter');\n tools1.insertBefore(delimiter1, this.buttons.link);\n applyDiv.append(delimiter3, this.linkApplyButton);\n tools2.append(this.linkBackButton, delimiter2, this.linkInput, applyDiv);\n //tools1.insertBefore(delimiter2, this.buttons.link.nextSibling);\n\n this.wrapper.append(tools1, tools2);\n this.container.append(this.wrapper);\n document.body.append(this.container);\n \n window.addEventListener('resize', () => {\n this.hide();\n });\n }\n\n public showLinkEditor() {\n if(!this.container || !this.container.classList.contains('is-visible')) { // * if not inited yet (Ctrl+A + Ctrl+K)\n this.show();\n }\n\n const button = this.buttons.link;\n this.container.classList.add('is-link');\n\n const selection = document.getSelection();\n this.savedRange = selection.getRangeAt(0);\n \n if(button.classList.contains('active')) {\n const startContainer = this.savedRange.startContainer;\n const anchor = startContainer.parentElement as HTMLAnchorElement;\n this.linkInput.value = anchor.href;\n } else {\n this.linkInput.value = '';\n }\n\n this.setTooltipPosition(true);\n\n setTimeout(() => {\n this.linkInput.focus(); // !!! instant focus will break animation\n }, 200);\n this.linkInput.classList.toggle('is-valid', this.isLinkValid());\n }\n\n private applyLink(e: Event) {\n cancelEvent(e);\n this.resetSelection();\n this.appImManager.chat.input.applyMarkdown('link', this.linkInput.value);\n setTimeout(() => {\n this.hide();\n }, 0);\n }\n\n private isLinkValid() {\n return !this.linkInput.value.length || !!RichTextProcessor.matchUrl(this.linkInput.value);\n }\n\n private resetSelection(range: Range = this.savedRange) {\n const selection = window.getSelection();\n selection.removeAllRanges();\n selection.addRange(range);\n this.appImManager.chat.input.messageInput.focus();\n }\n\n public hide() {\n //return;\n\n if(this.init) return;\n\n this.container.classList.remove('is-visible');\n //document.removeEventListener('mouseup', this.onMouseUp);\n document.removeEventListener('mouseup', this.onMouseUpSingle);\n this.waitingForMouseUp = false;\n\n appNavigationController.removeByType('markup');\n\n if(this.hideTimeout) clearTimeout(this.hideTimeout);\n this.hideTimeout = window.setTimeout(() => {\n this.hideTimeout = undefined;\n this.container.classList.add('hide');\n this.container.classList.remove('is-link');\n }, 200);\n }\n\n public getActiveMarkupButton() {\n const nodes = getSelectedNodes();\n const parents = [...new Set(nodes.map(node => node.parentNode))];\n //if(parents.length > 1 && parents) return [];\n\n const currentMarkups: Set<HTMLElement> = new Set();\n (parents as HTMLElement[]).forEach(node => {\n for(const type in markdownTags) {\n const tag = markdownTags[type as MarkdownType];\n const closest = node.closest(tag.match + ', [contenteditable]');\n if(closest !== this.appImManager.chat.input.messageInput) {\n currentMarkups.add(this.buttons[type as MarkdownType]);\n }\n }\n });\n \n\n return [...currentMarkups];\n }\n\n public setActiveMarkupButton() {\n const activeButtons = this.getActiveMarkupButton();\n\n for(const i in this.buttons) {\n // @ts-ignore\n const button = this.buttons[i];\n button.classList.toggle('active', activeButtons.includes(button));\n }\n }\n\n private setTooltipPosition(isLinkToggle = false) {\n const selection = document.getSelection();\n const range = selection.getRangeAt(0);\n\n const bodyRect = document.body.getBoundingClientRect();\n const selectionRect = range.getBoundingClientRect();\n const inputRect = this.appImManager.chat.input.rowsWrapper.getBoundingClientRect();\n\n this.container.style.maxWidth = inputRect.width + 'px';\n\n const selectionTop = selectionRect.top + (bodyRect.top * -1);\n \n const currentTools = this.container.classList.contains('is-link') ? this.wrapper.lastElementChild : this.wrapper.firstElementChild;\n\n const sizesRect = currentTools.getBoundingClientRect();\n const top = selectionTop - sizesRect.height - 8;\n \n const minX = inputRect.left;\n const maxX = (inputRect.left + inputRect.width) - Math.min(inputRect.width, sizesRect.width);\n let left: number;\n if(isLinkToggle) {\n const containerRect = this.container.getBoundingClientRect();\n left = clamp(containerRect.left, minX, maxX);\n } else {\n const x = selectionRect.left + (selectionRect.width - sizesRect.width) / 2;\n left = clamp(x, minX, maxX);\n }\n\n /* const isClamped = x !== minX && x !== maxX && (left === minX || left === maxX || this.container.getBoundingClientRect().left >= maxX);\n\n if(isLinkToggle && this.container.classList.contains('is-link') && !isClamped) return; */\n \n this.container.style.transform = `translate3d(${left}px, ${top}px, 0)`;\n }\n\n public show() {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n if(isSelectionEmpty()) {\n this.hide();\n return;\n }\n\n if(this.hideTimeout !== undefined) {\n clearTimeout(this.hideTimeout);\n }\n\n if(this.container.classList.contains('is-visible')) {\n return;\n }\n\n this.setActiveMarkupButton();\n \n this.container.classList.remove('is-link');\n const isFirstShow = this.container.classList.contains('hide');\n if(isFirstShow) {\n this.container.classList.remove('hide');\n this.container.classList.add('no-transition');\n }\n \n this.setTooltipPosition();\n \n if(isFirstShow) {\n void this.container.offsetLeft; // reflow\n this.container.classList.remove('no-transition');\n }\n \n this.container.classList.add('is-visible');\n\n if(!isMobile) {\n appNavigationController.pushItem({\n type: 'markup',\n onPop: () => {\n this.hide();\n }\n });\n }\n\n //this.log('selection', selectionRect, activeButton);\n }\n\n /* private onMouseUp = (e: Event) => {\n this.log('onMouseUp');\n if(findUpClassName(e.target, 'markup-tooltip')) return;\n\n this.hide();\n //document.removeEventListener('mouseup', this.onMouseUp);\n }; */\n\n private onMouseUpSingle = (e: Event) => {\n //this.log('onMouseUpSingle');\n this.waitingForMouseUp = false;\n\n if(isTouchSupported) {\n cancelEvent(e);\n if(this.mouseUpCounter++ === 0) {\n this.resetSelection(this.savedRange);\n } else {\n this.hide();\n return;\n }\n }\n\n this.show();\n\n //!isTouchSupported && document.addEventListener('mouseup', this.onMouseUp);\n };\n\n public setMouseUpEvent() {\n if(this.waitingForMouseUp) return;\n this.waitingForMouseUp = true;\n\n //this.log('setMouseUpEvent');\n\n document.addEventListener('mouseup', this.onMouseUpSingle, {once: true});\n }\n\n public cancelClosening() {\n if(isTouchSupported && !isApple) {\n document.removeEventListener('mouseup', this.onMouseUpSingle);\n document.addEventListener('mouseup', (e) => {\n cancelEvent(e);\n this.mouseUpCounter = 1;\n this.waitingForMouseUp = false;\n this.setMouseUpEvent();\n }, {once: true});\n }\n }\n\n public handleSelection() {\n if(this.addedListener) return;\n this.addedListener = true;\n document.addEventListener('selectionchange', (e) => {\n //this.log('selectionchange');\n\n if(document.activeElement === this.linkInput) {\n return;\n }\n\n if(document.activeElement !== this.appImManager.chat.input.messageInput) {\n this.hide();\n return;\n }\n\n const selection = document.getSelection();\n if(isSelectionEmpty(selection)) {\n this.hide();\n return;\n }\n\n if(isTouchSupported) {\n if(isApple) {\n this.show();\n this.setTooltipPosition(); // * because can skip this in .show();\n } else {\n if(this.mouseUpCounter === 2) {\n this.mouseUpCounter = 0;\n return;\n }\n\n this.savedRange = selection.getRangeAt(0);\n this.setMouseUpEvent();\n /* document.addEventListener('touchend', (e) => {\n cancelEvent(e);\n this.resetSelection(range);\n this.show();\n }, {once: true, passive: false}); */\n }\n } else {\n this.setMouseUpEvent();\n }\n });\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { generatePathData } from \"../../helpers/dom\";\nimport { i18n, LangPackKey } from \"../../lib/langPack\";\n\nexport default class ChatDragAndDrop {\n container: HTMLDivElement;\n svg: SVGSVGElement;\n outlineWrapper: HTMLDivElement;\n path: SVGPathElement;\n\n constructor(appendTo: HTMLElement, private options: {\n icon: string,\n header: LangPackKey,\n subtitle: LangPackKey,\n onDrop: (e: DragEvent) => void\n }) {\n this.container = document.createElement('div');\n this.container.classList.add('drop', 'z-depth-1');\n\n this.outlineWrapper = document.createElement('div');\n this.outlineWrapper.classList.add('drop-outline-wrapper');\n\n this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n this.svg.classList.add('drop-outline');\n\n this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n this.path.classList.add('drop-outline-path');\n\n const dropIcon = document.createElement('div');\n dropIcon.classList.add('drop-icon', 'tgico-' + options.icon);\n\n const dropHeader = document.createElement('div');\n dropHeader.classList.add('drop-header');\n dropHeader.append(i18n(options.header));\n\n const dropSubtitle = document.createElement('div');\n dropSubtitle.classList.add('drop-subtitle');\n dropSubtitle.append(i18n(options.subtitle));\n\n this.svg.append(this.path);\n this.outlineWrapper.append(this.svg);\n\n this.container.append(this.outlineWrapper, dropIcon, dropHeader, dropSubtitle);\n appendTo.append(this.container);\n\n this.container.addEventListener('dragover', this.onDragOver);\n this.container.addEventListener('dragleave', this.onDragLeave);\n this.container.addEventListener('drop', this.onDrop);\n }\n\n onDragOver = (e: DragEvent) => {\n this.container.classList.add('is-dragover');\n //SetTransition(this.container, 'is-dragover', true, 500);\n };\n\n onDragLeave = (e: DragEvent) => {\n this.container.classList.remove('is-dragover');\n //SetTransition(this.container, 'is-dragover', false, 500);\n };\n\n onDrop = (e: DragEvent) => {\n this.options.onDrop(e);\n };\n\n destroy() {\n delete this.options;\n this.container.remove();\n this.container.removeEventListener('dragover', this.onDragOver);\n this.container.removeEventListener('dragleave', this.onDragLeave);\n this.container.removeEventListener('drop', this.onDrop);\n }\n\n setPath() {\n const rect = this.outlineWrapper.getBoundingClientRect();\n this.svg.setAttributeNS(null, 'preserveAspectRatio', 'none');\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${rect.width} ${rect.height}`);\n this.svg.setAttributeNS(null, 'width', `${rect.width}`);\n this.svg.setAttributeNS(null, 'height', `${rect.height}`);\n\n const radius = 10;\n //const strokeWidth = 2;\n const sizeX = rect.width - radius;\n const sizeY = rect.height - radius;\n const pos = radius / 2;\n const d = generatePathData(pos, pos, sizeX, sizeY, radius, radius, radius, radius);\n this.path.setAttributeNS(null, 'd', d);\n }\n}","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\n//import apiManager from '../mtproto/apiManager';\nimport animationIntersector from '../../components/animationIntersector';\nimport appSidebarLeft, { LEFT_COLUMN_ACTIVE_CLASSNAME } from \"../../components/sidebarLeft\";\nimport appSidebarRight, { RIGHT_COLUMN_ACTIVE_CLASSNAME } from '../../components/sidebarRight';\nimport mediaSizes, { ScreenSize } from '../../helpers/mediaSizes';\nimport { logger, LogLevels } from \"../logger\";\nimport apiManager from '../mtproto/mtprotoworker';\nimport rootScope from '../rootScope';\nimport apiUpdatesManager from './apiUpdatesManager';\nimport appUsersManager from \"./appUsersManager\";\nimport Chat, { ChatType } from '../../components/chat/chat';\nimport appChatsManager from './appChatsManager';\nimport appDocsManager from './appDocsManager';\nimport appInlineBotsManager from './appInlineBotsManager';\nimport appMessagesManager from './appMessagesManager';\nimport appPeersManager from './appPeersManager';\nimport appPhotosManager from './appPhotosManager';\nimport appProfileManager from './appProfileManager';\nimport appStickersManager from './appStickersManager';\nimport appWebPagesManager from './appWebPagesManager';\nimport { blurActiveElement, cancelEvent, disableTransition, placeCaretAtEnd, replaceContent, whichChild } from '../../helpers/dom';\nimport PopupNewMedia from '../../components/popups/newMedia';\nimport MarkupTooltip from '../../components/chat/markupTooltip';\nimport { isTouchSupported } from '../../helpers/touchSupport';\nimport appPollsManager from './appPollsManager';\nimport SetTransition from '../../components/singleTransition';\nimport ChatDragAndDrop from '../../components/chat/dragAndDrop';\nimport { debounce, pause, doubleRaf } from '../../helpers/schedulers';\nimport lottieLoader from '../lottieLoader';\nimport useHeavyAnimationCheck, { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';\nimport appDraftsManager from './appDraftsManager';\nimport serverTimeManager from '../mtproto/serverTimeManager';\nimport sessionStorage from '../sessionStorage';\nimport appDownloadManager from './appDownloadManager';\nimport appStateManager, { AppStateManager } from './appStateManager';\nimport { MOUNT_CLASS_TO } from '../../config/debug';\nimport appNavigationController from '../../components/appNavigationController';\nimport appNotificationsManager from './appNotificationsManager';\nimport AppPrivateSearchTab from '../../components/sidebarRight/tabs/search';\nimport { i18n, LangPackKey } from '../langPack';\nimport { SendMessageAction } from '../../layer';\nimport { hslaStringToHex } from '../../helpers/color';\nimport { copy, getObjectKeysAndSort } from '../../helpers/object';\nimport { getFilesFromEvent } from '../../helpers/files';\nimport PeerTitle from '../../components/peerTitle';\n\n//console.log('appImManager included33!');\n\nappSidebarLeft; // just to include\n\nexport const CHAT_ANIMATION_GROUP = 'chat';\nconst FOCUS_EVENT_NAME = isTouchSupported ? 'touchstart' : 'mousemove';\n\nexport type ChatSavedPosition = {\n mids: number[], \n top: number\n};\n\nexport class AppImManager {\n public columnEl = document.getElementById('column-center') as HTMLDivElement;\n public chatsContainer: HTMLElement;\n\n public offline = false;\n public updateStatusInterval = 0;\n\n public log: ReturnType<typeof logger>;\n\n public setPeerPromise: Promise<void> = null;\n\n public tabId = -1;\n \n public chats: Chat[] = [];\n private prevTab: HTMLElement;\n private chatsSelectTabDebounced: () => void;\n \n public markupTooltip: MarkupTooltip;\n private themeColorElem: Element;\n private backgroundPromises: {[slug: string]: Promise<string>} = {};\n\n get myId() {\n return rootScope.myId;\n }\n\n get chat(): Chat {\n return this.chats[this.chats.length - 1];\n }\n\n constructor() {\n apiUpdatesManager.attach();\n\n this.log = logger('IM', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);\n\n this.selectTab(0);\n \n window.addEventListener('blur', () => {\n animationIntersector.checkAnimations(true);\n \n this.offline = rootScope.idle.isIDLE = true;\n this.updateStatus();\n clearInterval(this.updateStatusInterval);\n rootScope.broadcast('idle', rootScope.idle.isIDLE);\n \n window.addEventListener('focus', () => {\n this.offline = rootScope.idle.isIDLE = false;\n this.updateStatus();\n this.updateStatusInterval = window.setInterval(() => this.updateStatus(), 50e3);\n \n // в обратном порядке\n animationIntersector.checkAnimations(false);\n\n rootScope.broadcast('idle', rootScope.idle.isIDLE);\n }, {once: true});\n });\n\n // * Prevent setting online after reloading page\n window.addEventListener(FOCUS_EVENT_NAME, () => {\n this.updateStatusInterval = window.setInterval(() => this.updateStatus(), 50e3);\n this.updateStatus();\n\n this.offline = rootScope.idle.isIDLE = false;\n rootScope.broadcast('idle', rootScope.idle.isIDLE);\n }, {once: true, passive: true});\n\n this.chatsContainer = document.createElement('div');\n this.chatsContainer.classList.add('chats-container', 'tabs-container');\n this.chatsContainer.dataset.animation = 'navigation';\n\n this.columnEl.append(this.chatsContainer);\n \n this.createNewChat();\n this.chatsSelectTab(this.chat.container);\n\n appNavigationController.onHashChange = this.onHashChange;\n //window.addEventListener('hashchange', this.onHashChange);\n\n this.setSettings();\n rootScope.on('settings_updated', this.setSettings);\n\n useHeavyAnimationCheck(() => {\n animationIntersector.setOnlyOnePlayableGroup('lock');\n animationIntersector.checkAnimations(true);\n }, () => {\n animationIntersector.setOnlyOnePlayableGroup('');\n animationIntersector.checkAnimations(false);\n });\n\n this.applyCurrentTheme();\n\n // * fix simultaneous opened both sidebars, can happen when floating sidebar is opened with left sidebar\n mediaSizes.addEventListener('changeScreen', (from, to) => {\n if(document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME) \n && document.body.classList.contains(RIGHT_COLUMN_ACTIVE_CLASSNAME)) {\n appSidebarRight.toggleSidebar(false);\n }\n });\n\n rootScope.on('history_focus', (e) => {\n const {peerId, mid} = e;\n this.setInnerPeer(peerId, mid);\n });\n\n rootScope.on('peer_changing', (chat) => {\n this.saveChatPosition(chat);\n });\n\n sessionStorage.get('chatPositions').then((c) => {\n sessionStorage.setToCache('chatPositions', c || {});\n });\n }\n\n private onHashChange = () => {\n const hash = location.hash;\n const splitted = hash.split('?');\n\n if(!splitted[1]) {\n return;\n }\n\n const params: any = {};\n splitted[1].split('&').forEach(item => {\n params[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);\n });\n\n this.log('hashchange', hash, splitted[0], params);\n\n switch(splitted[0]) {\n case '#/im': {\n const p = params.p;\n let postId = params.post !== undefined ? appMessagesManager.generateMessageId(+params.post) : undefined;\n\n switch(p[0]) {\n case '@': {\n this.openUsername(p, postId);\n break;\n }\n\n default: { // peerId\n this.setInnerPeer(postId ? -+p : +p, postId);\n break;\n }\n }\n }\n }\n\n //appNavigationController.replaceState();\n //location.hash = '';\n };\n\n public openUsername(username: string, msgId?: number) {\n return appUsersManager.resolveUsername(username).then(peer => {\n const isUser = peer._ === 'user';\n const peerId = isUser ? peer.id : -peer.id;\n\n return this.setInnerPeer(peerId, msgId);\n });\n }\n\n public setCurrentBackground(broadcastEvent = false) {\n const theme = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme);\n\n if(theme.background.type === 'image' || (theme.background.type === 'default' && theme.background.slug)) {\n const defaultTheme = AppStateManager.STATE_INIT.settings.themes.find(t => t.name === theme.name);\n const isDefaultBackground = theme.background.blur === defaultTheme.background.blur && \n theme.background.slug === defaultTheme.background.slug;\n\n if(!isDefaultBackground) {\n return this.getBackground(theme.background.slug).then((url) => {\n return this.setBackground(url, broadcastEvent);\n }, () => { // * if NO_ENTRY_FOUND\n theme.background = copy(defaultTheme.background); // * reset background\n return this.setBackground('', true);\n });\n }\n }\n \n return this.setBackground('', broadcastEvent);\n }\n\n private getBackground(slug: string) {\n if(this.backgroundPromises[slug]) return this.backgroundPromises[slug];\n return this.backgroundPromises[slug] = appDownloadManager.cacheStorage.getFile('backgrounds/' + slug).then(blob => {\n return URL.createObjectURL(blob);\n });\n }\n\n public setBackground(url: string, broadcastEvent = true): Promise<void> {\n const promises = this.chats.map(chat => chat.setBackground(url));\n return promises[promises.length - 1].then(() => {\n if(broadcastEvent) {\n rootScope.broadcast('background_change');\n }\n });\n }\n\n public saveChatPosition(chat: Chat) {\n if(!(['chat', 'discussion'] as ChatType[]).includes(chat.type) || !chat.peerId) {\n return;\n }\n\n //const bubble = chat.bubbles.getBubbleByPoint('top');\n //if(bubble) {\n //const top = bubble.getBoundingClientRect().top;\n const top = chat.bubbles.scrollable.scrollTop;\n\n const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');\n\n const chatPositions = sessionStorage.getFromCache('chatPositions');\n if(!(chat.bubbles.scrollable.getDistanceToEnd() <= 16 && chat.bubbles.scrollable.loadedAll.bottom) && Object.keys(chat.bubbles.bubbles).length) {\n const position = {\n mids: getObjectKeysAndSort(chat.bubbles.bubbles, 'desc'),\n top\n };\n\n chatPositions[key] = position;\n\n this.log('saved chat position:', position);\n } else {\n delete chatPositions[key];\n\n this.log('deleted chat position');\n }\n\n sessionStorage.set({chatPositions}, true);\n //}\n }\n\n public getChatSavedPosition(chat: Chat): ChatSavedPosition {\n if(!(['chat', 'discussion'] as ChatType[]).includes(chat.type) || !chat.peerId) {\n return;\n }\n \n const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');\n const cache = sessionStorage.getFromCache('chatPositions');\n return cache && cache[key];\n }\n\n public applyHighlightningColor() {\n let hsla: string;\n const theme = rootScope.settings.themes.find(t => t.name === rootScope.settings.theme);\n if(theme.background.highlightningColor) {\n hsla = theme.background.highlightningColor;\n document.documentElement.style.setProperty('--message-highlightning-color', hsla);\n } else {\n document.documentElement.style.removeProperty('--message-highlightning-color');\n }\n\n let themeColor = '#ffffff';\n if(hsla) {\n themeColor = hslaStringToHex(hsla);\n }\n\n if(this.themeColorElem === undefined) {\n this.themeColorElem = document.head.querySelector('[name=\"theme-color\"]') as Element || null;\n }\n\n if(this.themeColorElem) {\n this.themeColorElem.setAttribute('content', themeColor);\n }\n }\n\n public applyCurrentTheme(slug?: string, backgroundUrl?: string, broadcastEvent?: boolean) {\n this.applyHighlightningColor();\n\n document.documentElement.classList.toggle('night', rootScope.settings.theme === 'night');\n\n if(backgroundUrl) {\n this.backgroundPromises[slug] = Promise.resolve(backgroundUrl);\n }\n \n return this.setCurrentBackground(broadcastEvent === undefined ? !!slug : broadcastEvent);\n }\n\n private setSettings = () => {\n document.documentElement.style.setProperty('--messages-text-size', rootScope.settings.messagesTextSize + 'px');\n \n document.body.classList.toggle('animation-level-0', !rootScope.settings.animationsEnabled);\n document.body.classList.toggle('animation-level-1', false);\n document.body.classList.toggle('animation-level-2', rootScope.settings.animationsEnabled);\n\n this.chatsSelectTabDebounced = debounce(() => {\n const topbar = this.chat.topbar;\n if(topbar.pinnedMessage) { // * буду молиться богам, чтобы это ничего не сломало, но это исправляет получение пиннеда после анимации\n topbar.pinnedMessage.setCorrectIndex(0);\n }\n\n apiManager.setQueueId(this.chat.bubbles.lazyLoadQueue.queueId);\n }, rootScope.settings.animationsEnabled ? 250 : 0, false, true);\n\n lottieLoader.setLoop(rootScope.settings.stickers.loop);\n animationIntersector.checkAnimations(false);\n \n for(const chat of this.chats) {\n chat.setAutoDownloadMedia();\n }\n };\n\n // * не могу использовать тут TransitionSlider, так как мне нужен отрисованный блок рядом \n // * (или под текущим чатом) чтобы правильно отрендерить чат (напр. scrollTop)\n private chatsSelectTab(tab: HTMLElement, animate?: boolean) {\n if(this.prevTab === tab) {\n return;\n }\n\n if(animate === false && this.prevTab) { // * will be used for Safari iOS history swipe\n disableTransition([tab, this.prevTab].filter(Boolean));\n }\n\n if(this.prevTab) {\n this.prevTab.classList.remove('active');\n this.chatsSelectTabDebounced();\n\n // ! нужно переделать на animation, так как при лаге анимация будет длиться не 250мс\n if(rootScope.settings.animationsEnabled && animate !== false) { \n dispatchHeavyAnimationEvent(pause(250 + 150), 250 + 150);\n }\n\n const prevIdx = whichChild(this.prevTab);\n const idx = whichChild(tab);\n if(idx > prevIdx) {\n appNavigationController.pushItem({\n type: 'chat', \n onPop: (canAnimate) => {\n this.setPeer(0, undefined, canAnimate);\n blurActiveElement();\n }\n });\n }\n }\n\n tab.classList.add('active');\n this.prevTab = tab;\n }\n\n private init() {\n document.addEventListener('paste', this.onDocumentPaste, true);\n \n const onKeyDown = (e: KeyboardEvent) => {\n if(rootScope.overlayIsActive) return;\n \n const target = e.target as HTMLElement;\n \n //if(target.tagName === 'INPUT') return;\n \n //this.log('onkeydown', e, document.activeElement);\n\n const chat = this.chat;\n\n if(e.key === 'Meta' || e.key === 'Control') {\n return;\n } else if(e.code === \"KeyC\" && (e.ctrlKey || e.metaKey) && target.tagName !== 'INPUT') {\n return;\n } else if(e.code === 'ArrowUp') {\n if(!chat.input.editMsgId && chat.input.isInputEmpty()) {\n const history = appMessagesManager.getHistoryStorage(chat.peerId, chat.threadId);\n if(history.history.length) {\n let goodMid: number;\n for(const mid of history.history.slice) {\n const message = chat.getMessage(mid);\n const good = this.myId === chat.peerId ? message.fromId === this.myId : message.pFlags.out;\n\n if(good) {\n if(appMessagesManager.canEditMessage(chat.getMessage(mid), 'text')) {\n goodMid = mid;\n break;\n }\n\n // * this check will allow editing only last message\n //break;\n }\n }\n \n if(goodMid) {\n chat.input.initMessageEditing(goodMid);\n cancelEvent(e); // * prevent from scrolling\n }\n }\n }\n }\n \n if(chat.input.messageInput && e.target !== chat.input.messageInput && target.tagName !== 'INPUT' && !target.hasAttribute('contenteditable') && !isTouchSupported) {\n chat.input.messageInput.focus();\n placeCaretAtEnd(chat.input.messageInput);\n }\n };\n \n document.body.addEventListener('keydown', onKeyDown);\n\n rootScope.addEventListener('history_multiappend', (e) => {\n const msgIdsByPeer = e;\n\n for(const peerId in msgIdsByPeer) {\n appSidebarRight.sharedMediaTab.renderNewMessages(+peerId, Array.from(msgIdsByPeer[peerId]));\n }\n });\n \n rootScope.addEventListener('history_delete', (e) => {\n const {peerId, msgs} = e;\n\n const mids = Object.keys(msgs).map(s => +s);\n appSidebarRight.sharedMediaTab.deleteDeletedMessages(peerId, mids);\n });\n\n // Calls when message successfully sent and we have an id\n rootScope.addEventListener('message_sent', (e) => {\n const {storage, tempId, mid} = e;\n const message = appMessagesManager.getMessageFromStorage(storage, mid);\n appSidebarRight.sharedMediaTab.renderNewMessages(message.peerId, [mid]);\n });\n\n if(!isTouchSupported) {\n this.attachDragAndDropListeners();\n }\n\n //if(!isTouchSupported) {\n this.markupTooltip = new MarkupTooltip(this);\n this.markupTooltip.handleSelection();\n //}\n }\n\n private attachDragAndDropListeners() {\n const drops: ChatDragAndDrop[] = [];\n let mounted = false;\n const toggle = async(e: DragEvent, mount: boolean) => {\n if(mount === mounted) return;\n\n const _types = e.dataTransfer.types;\n // @ts-ignore\n const isFiles = _types.contains ? _types.contains('Files') : _types.indexOf('Files') >= 0;\n\n if(!isFiles || !this.canDrag()) { // * skip dragging text case\n counter = 0;\n return;\n }\n\n if(mount && !drops.length) {\n const types: string[] = await getFilesFromEvent(e, true)\n const force = isFiles && !types.length; // * can't get file items not from 'drop' on Safari\n \n const foundMedia = types.filter(t => ['image', 'video'].includes(t.split('/')[0])).length;\n const foundDocuments = types.length - foundMedia;\n \n this.log('drag files', types);\n \n if(types.length || force) {\n drops.push(new ChatDragAndDrop(dropsContainer, {\n icon: 'dragfiles',\n header: 'Chat.DropTitle',\n subtitle: 'Chat.DropAsFilesDesc',\n onDrop: (e: DragEvent) => {\n toggle(e, false);\n appImManager.log('drop', e);\n appImManager.onDocumentPaste(e, 'document');\n }\n }));\n }\n \n if((foundMedia && !foundDocuments) || force) {\n drops.push(new ChatDragAndDrop(dropsContainer, {\n icon: 'dragmedia',\n header: 'Chat.DropTitle',\n subtitle: 'Chat.DropQuickDesc',\n onDrop: (e: DragEvent) => {\n toggle(e, false);\n appImManager.log('drop', e);\n appImManager.onDocumentPaste(e, 'media');\n }\n }));\n }\n \n this.chat.container.append(dropsContainer);\n }\n\n //if(!mount) return;\n\n SetTransition(dropsContainer, 'is-visible', mount, 200, () => {\n if(!mount) {\n drops.forEach(drop => {\n drop.destroy();\n });\n\n drops.length = 0;\n }\n });\n\n if(mount) {\n drops.forEach(drop => {\n drop.setPath();\n });\n } else {\n counter = 0;\n }\n\n document.body.classList.toggle('is-dragging', mount);\n mounted = mount;\n };\n\n /* document.body.addEventListener('dragover', (e) => {\n cancelEvent(e);\n }); */\n\n let counter = 0;\n document.body.addEventListener('dragenter', (e) => {\n counter++;\n });\n\n document.body.addEventListener('dragover', (e) => {\n //this.log('dragover', e/* , e.dataTransfer.types[0] */);\n toggle(e, true);\n cancelEvent(e);\n });\n\n document.body.addEventListener('dragleave', (e) => {\n //this.log('dragleave', e, counter);\n //if((e.pageX <= 0 || e.pageX >= appPhotosManager.windowW) || (e.pageY <= 0 || e.pageY >= appPhotosManager.windowH)) {\n counter--;\n if(counter === 0) { \n //if(!findUpClassName(e.target, 'drops-container')) {\n toggle(e, false);\n }\n });\n\n const dropsContainer = document.createElement('div');\n dropsContainer.classList.add('drops-container');\n }\n\n private canDrag() {\n const peerId = this.chat?.peerId;\n return !(!peerId || rootScope.overlayIsActive || (peerId < 0 && !appChatsManager.hasRights(peerId, 'send_media')));\n }\n\n private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => {\n if(!this.canDrag()) return;\n\n //console.log('document paste');\n //console.log('item', event.clipboardData.getData());\n\n if(e instanceof DragEvent) {\n const _types = e.dataTransfer.types;\n // @ts-ignore\n const isFiles = _types.contains ? _types.contains('Files') : _types.indexOf('Files') >= 0;\n if(isFiles) {\n cancelEvent(e);\n }\n }\n \n getFilesFromEvent(e).then((files: File[]) => {\n if(files.length) {\n if(attachType === 'media' && files.find(file => !['image', 'video'].includes(file.type.split('/')[0]))) {\n attachType = 'document';\n }\n \n const chatInput = this.chat.input;\n chatInput.willAttachType = attachType || (files[0].type.indexOf('image/') === 0 ? 'media' : \"document\");\n new PopupNewMedia(this.chat, files, chatInput.willAttachType);\n }\n });\n };\n\n public selectTab(id: number, animate?: boolean) {\n if(animate === false) { // * will be used for Safari iOS history swipe\n disableTransition([appSidebarLeft.sidebarEl, this.columnEl, appSidebarRight.sidebarEl]);\n }\n\n document.body.classList.toggle(LEFT_COLUMN_ACTIVE_CLASSNAME, id === 0);\n\n const prevTabId = this.tabId;\n\n this.log('selectTab', id, prevTabId);\n\n let animationPromise: Promise<any> = doubleRaf();\n if(prevTabId !== -1 && prevTabId !== id && rootScope.settings.animationsEnabled && animate !== false) {\n const transitionTime = (mediaSizes.isMobile ? 250 : 200) + 100; // * cause transition time could be > 250ms\n animationPromise = pause(transitionTime);\n dispatchHeavyAnimationEvent(animationPromise, transitionTime);\n\n this.columnEl.classList.add('disable-hover');\n animationPromise.finally(() => {\n this.columnEl.classList.remove('disable-hover');\n });\n }\n\n this.tabId = id;\n if(mediaSizes.isMobile && prevTabId === 2 && id < 2) {\n document.body.classList.remove(RIGHT_COLUMN_ACTIVE_CLASSNAME);\n }\n\n if(prevTabId !== -1 && id > prevTabId) {\n if(id < 2 || !appNavigationController.findItemByType('im')) {\n appNavigationController.pushItem({\n type: 'im', \n onPop: (canAnimate) => {\n //this.selectTab(prevTabId, !isSafari);\n this.setPeer(0, undefined, canAnimate);\n }\n });\n }\n }\n\n rootScope.broadcast('im_tab_change', id);\n\n //this._selectTab(id, mediaSizes.isMobile);\n //document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, id === 2);\n\n return animationPromise;\n }\n \n public updateStatus() {\n if(!this.myId) return Promise.resolve();\n \n appUsersManager.setUserStatus(this.myId, this.offline);\n return apiManager.invokeApi('account.updateStatus', {offline: this.offline});\n }\n\n private createNewChat() {\n const chat = new Chat(this, appChatsManager, appDocsManager, appInlineBotsManager, appMessagesManager, appPeersManager, appPhotosManager, appProfileManager, appStickersManager, appUsersManager, appWebPagesManager, appPollsManager, apiManager, appDraftsManager, serverTimeManager, sessionStorage, appNotificationsManager);\n\n if(this.chats.length) {\n chat.backgroundEl.append(this.chat.backgroundEl.lastElementChild.cloneNode(true));\n }\n\n this.chats.push(chat);\n }\n\n private spliceChats(fromIndex: number, justReturn = true, animate?: boolean, spliced?: Chat[]) {\n if(fromIndex >= this.chats.length) return;\n\n if(this.chats.length > 1 && justReturn) {\n rootScope.broadcast('peer_changing', this.chat);\n }\n\n if(!spliced) {\n spliced = this.chats.splice(fromIndex, this.chats.length - fromIndex);\n }\n\n // * -1 because one item is being sliced when closing the chat by calling .removeByType\n for(let i = 0; i < spliced.length - 1; ++i) {\n appNavigationController.removeByType('chat', true);\n }\n\n // * fix middle chat z-index on animation\n if(spliced.length > 1) {\n spliced.slice(0, -1).forEach(chat => {\n chat.container.remove();\n });\n }\n\n this.chatsSelectTab(this.chat.container, animate);\n\n if(justReturn) {\n rootScope.broadcast('peer_changed', this.chat.peerId);\n\n const searchTab = appSidebarRight.getTab(AppPrivateSearchTab);\n if(searchTab) {\n searchTab.close();\n }\n \n const isSet = appSidebarRight.sharedMediaTab.setPeer(this.chat.peerId, this.chat.threadId);\n if(isSet) {\n appSidebarRight.sharedMediaTab.loadSidebarMedia(true);\n appSidebarRight.sharedMediaTab.fillProfileElements();\n }\n \n /* setTimeout(() => {\n appSidebarRight.sharedMediaTab.loadSidebarMedia(false);\n }); */\n }\n \n setTimeout(() => {\n //chat.setPeer(0);\n spliced.forEach(chat => {\n chat.destroy();\n });\n }, 250 + 100);\n }\n\n public setPeer(peerId: number, lastMsgId?: number, animate?: boolean): boolean {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n const chat = this.chat;\n const chatIndex = this.chats.indexOf(chat);\n\n if(!peerId) {\n if(chatIndex > 0) {\n this.spliceChats(chatIndex, undefined, animate);\n return;\n } else if(mediaSizes.activeScreen === ScreenSize.medium) { // * floating sidebar case\n this.selectTab(+!this.tabId, animate);\n return;\n }\n } else if(chatIndex > 0 && chat.peerId && chat.peerId !== peerId) {\n // const firstChat = this.chats[0];\n // if(firstChat.peerId !== chat.peerId) {\n /* // * slice idx > 0, set background and slice first, so new one will be the first\n const spliced = this.chats.splice(1, this.chats.length - 1);\n this.createNewChat();\n this.chats.splice(0, 1); */\n const spliced = this.chats.splice(1, this.chats.length - 1);\n if(this.chat.peerId === peerId) {\n this.spliceChats(0, true, true, spliced);\n return;\n } else {\n const ret = this.setPeer(peerId, lastMsgId);\n this.spliceChats(0, false, false, spliced);\n return ret;\n }\n // } else {\n // this.spliceChats(1, false, animate);\n // }\n\n //return ret;\n }\n\n // * don't reset peer if returning\n if(peerId === chat.peerId && mediaSizes.activeScreen <= ScreenSize.medium && document.body.classList.contains(LEFT_COLUMN_ACTIVE_CLASSNAME)) {\n this.selectTab(1, animate);\n return false;\n }\n\n if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) {\n const result = chat.setPeer(peerId, lastMsgId);\n\n // * wait for cached render\n const promise = result?.cached ? result.promise : Promise.resolve();\n if(peerId) {\n promise.then(() => {\n //window.requestAnimationFrame(() => {\n setTimeout(() => { // * setTimeout is better here\n setTimeout(() => {\n this.chatsSelectTab(this.chat.container);\n }, 0);\n this.selectTab(1, animate);\n }, 0);\n });\n }\n }\n\n if(!peerId) {\n this.selectTab(0, animate);\n return false;\n }\n }\n\n public setInnerPeer(peerId: number, lastMsgId?: number, type: ChatType = 'chat', threadId?: number) {\n // * prevent opening already opened peer\n const existingIndex = this.chats.findIndex(chat => chat.peerId === peerId && chat.type === type);\n if(existingIndex !== -1) {\n this.spliceChats(existingIndex + 1);\n return this.setPeer(peerId, lastMsgId);\n }\n\n const chat = this.chat;\n if(!chat.init) { // * use first not inited chat\n this.createNewChat();\n }\n\n if(type) {\n this.chat.setType(type);\n\n if(threadId) {\n this.chat.threadId = threadId;\n }\n }\n\n //this.chatsSelectTab(this.chat.container);\n\n return this.setPeer(peerId, lastMsgId);\n }\n\n public openScheduled(peerId: number) {\n this.setInnerPeer(peerId, undefined, 'scheduled');\n }\n\n private getTypingElement(action: SendMessageAction) {\n const el = document.createElement('span');\n el.classList.add('peer-typing');\n el.dataset.action = action._;\n switch(action._) {\n case 'sendMessageTypingAction': {\n //default: {\n const c = 'peer-typing-text';\n el.classList.add(c);\n for(let i = 0; i < 3; ++i) {\n const dot = document.createElement('span');\n dot.className = c + '-dot';\n el.append(dot);\n }\n break;\n }\n\n case 'sendMessageUploadAudioAction':\n case 'sendMessageUploadDocumentAction':\n case 'sendMessageUploadRoundAction':\n case 'sendMessageUploadVideoAction':\n case 'sendMessageUploadPhotoAction': {\n const c = 'peer-typing-upload';\n el.classList.add(c);\n /* const trail = document.createElement('span');\n trail.className = c + '-trail';\n el.append(trail); */\n break;\n }\n\n case 'sendMessageRecordAudioAction':\n case 'sendMessageRecordRoundAction':\n case 'sendMessageRecordVideoAction': {\n const c = 'peer-typing-record';\n el.classList.add(c);\n break;\n }\n }\n\n return el;\n }\n\n public getPeerTyping(peerId: number, container?: HTMLElement) {\n if(!appUsersManager.isBot(peerId)) {\n const typings = appChatsManager.typingsInPeer[peerId];\n if(!typings || !typings.length) {\n return;\n }\n\n const typing = typings[0];\n\n const langPackKeys: {\n [peerType in 'private' | 'chat' | 'multi']?: Partial<{[action in SendMessageAction['_']]: LangPackKey}>\n } = {\n private: {\n 'sendMessageTypingAction': 'Peer.Activity.User.TypingText',\n 'sendMessageUploadAudioAction': 'Peer.Activity.User.SendingFile',\n 'sendMessageUploadDocumentAction': 'Peer.Activity.User.SendingFile',\n 'sendMessageUploadPhotoAction': 'Peer.Activity.User.SendingPhoto',\n 'sendMessageUploadVideoAction': 'Peer.Activity.User.SendingVideo',\n 'sendMessageUploadRoundAction': 'Peer.Activity.User.SendingVideo',\n 'sendMessageRecordVideoAction': 'Peer.Activity.User.RecordingVideo',\n 'sendMessageRecordAudioAction': 'Peer.Activity.User.RecordingAudio',\n 'sendMessageRecordRoundAction': 'Peer.Activity.User.RecordingVideo',\n 'sendMessageGamePlayAction': 'Peer.Activity.User.PlayingGame'\n },\n chat: {\n 'sendMessageTypingAction': 'Peer.Activity.Chat.TypingText',\n 'sendMessageUploadAudioAction': 'Peer.Activity.Chat.SendingFile',\n 'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.SendingFile',\n 'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.SendingPhoto',\n 'sendMessageUploadVideoAction': 'Peer.Activity.Chat.SendingVideo',\n 'sendMessageUploadRoundAction': 'Peer.Activity.Chat.SendingVideo',\n 'sendMessageRecordVideoAction': 'Peer.Activity.Chat.RecordingVideo',\n 'sendMessageRecordAudioAction': 'Peer.Activity.Chat.RecordingAudio',\n 'sendMessageRecordRoundAction': 'Peer.Activity.Chat.RecordingVideo',\n 'sendMessageGamePlayAction': 'Peer.Activity.Chat.PlayingGame'\n },\n multi: {\n 'sendMessageTypingAction': 'Peer.Activity.Chat.Multi.TypingText1',\n 'sendMessageUploadAudioAction': 'Peer.Activity.Chat.Multi.SendingFile1',\n 'sendMessageUploadDocumentAction': 'Peer.Activity.Chat.Multi.SendingFile1',\n 'sendMessageUploadPhotoAction': 'Peer.Activity.Chat.Multi.SendingPhoto1',\n 'sendMessageUploadVideoAction': 'Peer.Activity.Chat.Multi.SendingVideo1',\n 'sendMessageUploadRoundAction': 'Peer.Activity.Chat.Multi.SendingVideo1',\n 'sendMessageRecordVideoAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',\n 'sendMessageRecordAudioAction': 'Peer.Activity.Chat.Multi.RecordingAudio1',\n 'sendMessageRecordRoundAction': 'Peer.Activity.Chat.Multi.RecordingVideo1',\n 'sendMessageGamePlayAction': 'Peer.Activity.Chat.Multi.PlayingGame1'\n }\n };\n\n const mapa = peerId > 0 ? langPackKeys.private : (typings.length > 1 ? langPackKeys.multi : langPackKeys.chat);\n let action = typing.action;\n\n if(typings.length > 1) {\n const s: any = {};\n typings.forEach(typing => {\n const type = typing.action._;\n if(s[type] === undefined) s[type] = 0;\n ++s[type];\n });\n\n if(Object.keys(s).length > 1) {\n action = {\n _: 'sendMessageTypingAction'\n };\n }\n }\n\n const langPackKey = mapa[action._];\n if(!langPackKey) {\n return;\n }\n\n if(!container) {\n container = document.createElement('span');\n container.classList.add('online', 'peer-typing-container');\n }\n\n let typingElement = container.firstElementChild as HTMLElement;\n if(!typingElement) {\n typingElement = this.getTypingElement(action);\n container.prepend(typingElement);\n } else {\n if(typingElement.dataset.action !== action._) {\n typingElement.replaceWith(this.getTypingElement(action));\n }\n }\n\n let args: any[];\n if(peerId < 0) {\n args = [\n new PeerTitle({peerId: typing.userId, onlyFirstName: true}).element,\n typings.length - 1\n ];\n }\n const descriptionElement = i18n(langPackKey, args);\n descriptionElement.classList.add('peer-typing-description');\n\n if(container.childElementCount > 1) container.lastElementChild.replaceWith(descriptionElement);\n else container.append(descriptionElement);\n return container;\n }\n }\n\n public async getPeerStatus(peerId: number) {\n let subtitle: HTMLElement;\n if(!peerId) return '';\n\n if(peerId < 0) { // not human\n let span = this.getPeerTyping(peerId);\n if(span) {\n return span;\n }\n\n const chatInfo = await appProfileManager.getChatFull(-peerId) as any;\n this.chat.log('chatInfo res:', chatInfo);\n\n const participants_count = chatInfo.participants_count || (chatInfo.participants && chatInfo.participants.participants && chatInfo.participants.participants.length) || 1;\n //if(participants_count) {\n subtitle = appChatsManager.getChatMembersString(-peerId);\n\n if(participants_count < 2) return subtitle;\n /* const onlines = await appChatsManager.getOnlines(chat.id);\n if(onlines > 1) {\n subtitle += ', ' + numberThousandSplitter(onlines) + ' online';\n } */\n \n return subtitle;\n //}\n } else { // user\n const user = appUsersManager.getUser(peerId);\n \n if(rootScope.myId === peerId) {\n return '';\n } else if(user) {\n subtitle = appUsersManager.getUserStatusString(user.id);\n\n if(!appUsersManager.isBot(peerId)) {\n let span = this.getPeerTyping(peerId);\n if(!span && user.status?._ === 'userStatusOnline') {\n span = document.createElement('span');\n span.classList.add('online');\n span.append(subtitle);\n }\n\n if(span) {\n return span;\n }\n }\n \n return subtitle;\n }\n }\n }\n\n public setPeerStatus(peerId: number, element: HTMLElement, needClear: boolean, useWhitespace: boolean, middleware: () => boolean) {\n if(needClear) {\n element.innerHTML = useWhitespace ? '' : ''; // ! HERE U CAN FIND WHITESPACE\n }\n\n // * good good good\n const typingContainer = element.querySelector('.peer-typing-container') as HTMLElement;\n if(typingContainer && this.getPeerTyping(peerId, typingContainer)) {\n return;\n }\n\n this.getPeerStatus(peerId).then((subtitle) => {\n if(!middleware()) {\n return;\n }\n\n replaceContent(element, subtitle || (useWhitespace ? '' : ''));\n });\n }\n}\n\nconst appImManager = new AppImManager();\nMOUNT_CLASS_TO && (MOUNT_CLASS_TO.appImManager = appImManager);\nexport default appImManager;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { deferredPromise } from \"../helpers/cancellablePromise\";\nimport mediaSizes from \"../helpers/mediaSizes\";\nimport { isTouchSupported } from \"../helpers/touchSupport\";\nimport { isMobileSafari, isSafari } from \"../helpers/userAgent\";\nimport appDocsManager, { MyDocument } from \"../lib/appManagers/appDocsManager\";\nimport appImManager from \"../lib/appManagers/appImManager\";\nimport appMessagesManager from \"../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../lib/appManagers/appPeersManager\";\nimport appPhotosManager from \"../lib/appManagers/appPhotosManager\";\nimport { logger } from \"../lib/logger\";\nimport VideoPlayer from \"../lib/mediaPlayer\";\nimport { RichTextProcessor } from \"../lib/richtextprocessor\";\nimport rootScope from \"../lib/rootScope\";\nimport { cancelEvent, fillPropertyValue, generatePathData } from \"../helpers/dom\";\nimport animationIntersector from \"./animationIntersector\";\nimport appMediaPlaybackController from \"./appMediaPlaybackController\";\nimport AvatarElement from \"./avatar\";\nimport ButtonIcon from \"./buttonIcon\";\nimport { ButtonMenuItemOptions } from \"./buttonMenu\";\nimport ButtonMenuToggle from \"./buttonMenuToggle\";\nimport { LazyLoadQueueBase } from \"./lazyLoadQueue\";\nimport PopupForward from \"./popups/forward\";\nimport ProgressivePreloader from \"./preloader\";\nimport Scrollable from \"./scrollable\";\nimport appSidebarRight, { AppSidebarRight } from \"./sidebarRight\";\nimport SwipeHandler from \"./swipeHandler\";\nimport { months, ONE_DAY } from \"../helpers/date\";\nimport { SearchSuperContext } from \"./appSearchSuper.\";\nimport DEBUG from \"../config/debug\";\nimport appNavigationController from \"./appNavigationController\";\nimport { Message } from \"../layer\";\nimport { forEachReverse } from \"../helpers/array\";\nimport AppSharedMediaTab from \"./sidebarRight/tabs/sharedMedia\";\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\nimport renderImageFromUrl from \"../helpers/dom/renderImageFromUrl\";\nimport findUpAsChild from \"../helpers/dom/findUpAsChild\";\nimport getVisibleRect from \"../helpers/dom/getVisibleRect\";\n\n// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию\n// TODO: картинки \"обрезаются\" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)\n// TODO: видео в мобильной вёрстке, если показываются элементы управления: если свайпнуть в сторону, то элементы вернутся на место, т.е. прыгнут - это не ок, надо бы замаскировать\n\nconst MEDIA_VIEWER_CLASSNAME = 'media-viewer';\n\nclass AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType extends string, TargetType extends object> {\n public wholeDiv: HTMLElement;\n protected overlaysDiv: HTMLElement;\n protected author: {[k in 'container' | 'avatarEl' | 'nameEl' | 'date']: HTMLElement} = {} as any;\n protected content: {[k in 'main' | 'container' | 'media' | 'mover' | ContentAdditionType]: HTMLElement} = {} as any;\n public buttons: {[k in 'download' | 'close' | 'prev' | 'next' | 'mobile-close' | ButtonsAdditionType]: HTMLElement} = {} as any;\n \n protected tempId = 0;\n protected preloader: ProgressivePreloader = null;\n protected preloaderStreamable: ProgressivePreloader = null;\n\n protected lastTarget: HTMLElement = null;\n protected prevTargets: TargetType[] = [];\n protected nextTargets: TargetType[] = [];\n //protected targetContainer: HTMLElement = null;\n //protected loadMore: () => void = null;\n\n public log: ReturnType<typeof logger>; \n\n protected isFirstOpen = true;\n protected loadMediaPromiseUp: Promise<void> = null;\n protected loadMediaPromiseDown: Promise<void> = null;\n protected loadedAllMediaUp = false;\n protected loadedAllMediaDown = false;\n\n protected reverse = false; // reverse means next = higher msgid\n protected needLoadMore = true;\n\n protected pageEl = document.getElementById('page-chats') as HTMLDivElement;\n\n protected setMoverPromise: Promise<void>;\n protected setMoverAnimationPromise: Promise<void>;\n\n protected lazyLoadQueue: LazyLoadQueueBase;\n\n protected highlightSwitchersTimeout: number;\n\n protected onDownloadClick: (e: MouseEvent) => void;\n protected onPrevClick: (target: TargetType) => void;\n protected onNextClick: (target: TargetType) => void;\n protected loadMoreMedia: (older: boolean) => Promise<void>;\n \n constructor(topButtons: Array<keyof AppMediaViewerBase<ContentAdditionType, ButtonsAdditionType, TargetType>['buttons']>) {\n this.log = logger('AMV');\n this.preloader = new ProgressivePreloader();\n this.preloaderStreamable = new ProgressivePreloader({\n cancelable: false,\n streamable: true\n });\n this.preloader.construct();\n this.preloaderStreamable.construct();\n this.lazyLoadQueue = new LazyLoadQueueBase();\n\n this.wholeDiv = document.createElement('div');\n this.wholeDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-whole');\n\n this.overlaysDiv = document.createElement('div');\n this.overlaysDiv.classList.add('overlays');\n\n const mainDiv = document.createElement('div');\n mainDiv.classList.add(MEDIA_VIEWER_CLASSNAME);\n\n // * author\n this.author.container = document.createElement('div');\n this.author.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-author', 'no-select');\n\n this.author.avatarEl = new AvatarElement();\n this.author.avatarEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-userpic', 'avatar-44');\n\n this.author.nameEl = document.createElement('div');\n this.author.nameEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-name');\n\n this.author.date = document.createElement('div');\n this.author.date.classList.add(MEDIA_VIEWER_CLASSNAME + '-date');\n\n this.author.container.append(this.author.avatarEl, this.author.nameEl, this.author.date);\n\n // * buttons\n const buttonsDiv = document.createElement('div');\n buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons');\n\n topButtons.concat(['download', 'close']).forEach(name => {\n const button = ButtonIcon(name);\n this.buttons[name] = button;\n buttonsDiv.append(button);\n });\n\n // * content\n this.content.main = document.createElement('div');\n this.content.main.classList.add(MEDIA_VIEWER_CLASSNAME + '-content');\n\n this.content.container = document.createElement('div');\n this.content.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-container');\n\n this.content.media = document.createElement('div');\n this.content.media.classList.add(MEDIA_VIEWER_CLASSNAME + '-media');\n\n this.content.container.append(this.content.media);\n\n this.content.main.append(this.content.container);\n mainDiv.append(this.author.container, buttonsDiv, this.content.main);\n this.overlaysDiv.append(mainDiv);\n // * overlays end\n\n this.buttons[\"mobile-close\"] = ButtonIcon('close', {onlyMobile: true});\n\n this.buttons.prev = document.createElement('div');\n this.buttons.prev.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-left`;\n this.buttons.prev.innerHTML = `<span class=\"tgico-down ${MEDIA_VIEWER_CLASSNAME}-prev-button\"></span>`;\n\n this.buttons.next = document.createElement('div');\n this.buttons.next.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-right`;\n this.buttons.next.innerHTML = `<span class=\"tgico-down ${MEDIA_VIEWER_CLASSNAME}-next-button\"></span>`;\n\n this.wholeDiv.append(this.overlaysDiv, this.buttons['mobile-close'], this.buttons.prev, this.buttons.next);\n\n // * constructing html end\n \n this.setNewMover();\n }\n\n protected setListeners() {\n this.buttons.download.addEventListener('click', this.onDownloadClick);\n [this.buttons.close, this.buttons[\"mobile-close\"], this.preloaderStreamable.preloader].forEach(el => {\n el.addEventListener('click', this.close.bind(this));\n });\n\n this.buttons.prev.addEventListener('click', (e) => {\n cancelEvent(e);\n if(this.setMoverPromise) return;\n\n const target = this.prevTargets.pop();\n if(target) {\n this.onPrevClick(target);\n } else {\n this.buttons.prev.style.display = 'none';\n }\n });\n \n this.buttons.next.addEventListener('click', (e) => {\n cancelEvent(e);\n if(this.setMoverPromise) return;\n\n let target = this.nextTargets.shift();\n if(target) {\n this.onNextClick(target);\n } else {\n this.buttons.next.style.display = 'none';\n }\n });\n\n this.wholeDiv.addEventListener('click', this.onClick);\n\n if(isTouchSupported) {\n const swipeHandler = new SwipeHandler({\n element: this.wholeDiv, \n onSwipe: (xDiff, yDiff) => {\n if(VideoPlayer.isFullScreen()) {\n return;\n }\n //console.log(xDiff, yDiff);\n\n const percents = Math.abs(xDiff) / appPhotosManager.windowW;\n if(percents > .2 || xDiff > 125) {\n //console.log('will swipe', xDiff);\n\n if(xDiff < 0) {\n this.buttons.prev.click();\n } else {\n this.buttons.next.click();\n }\n\n return true;\n }\n\n const percentsY = Math.abs(yDiff) / appPhotosManager.windowH;\n if(percentsY > .2 || yDiff > 125) {\n this.buttons.close.click();\n return true;\n }\n\n return false;\n }, \n verifyTouchTarget: (evt) => {\n // * Fix for seek input\n if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) {\n return false;\n }\n\n return true;\n }\n });\n }\n }\n\n protected setBtnMenuToggle(buttons: ButtonMenuItemOptions[]) {\n const btnMenuToggle = ButtonMenuToggle({onlyMobile: true}, 'bottom-left', buttons);\n this.wholeDiv.append(btnMenuToggle);\n }\n\n public close(e?: MouseEvent) {\n if(e) {\n cancelEvent(e);\n }\n\n if(this.setMoverAnimationPromise) return;\n\n appNavigationController.removeByType('media');\n\n this.lazyLoadQueue.clear();\n\n const promise = this.setMoverToTarget(this.lastTarget, true).then(({onAnimationEnd}) => onAnimationEnd);\n\n this.lastTarget = null;\n this.prevTargets = [];\n this.nextTargets = [];\n this.loadedAllMediaUp = this.loadedAllMediaDown = false;\n this.loadMediaPromiseUp = this.loadMediaPromiseDown = null;\n this.setMoverPromise = null;\n this.tempId = -1;\n\n /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) {\n promise.then(() => {\n appSidebarRight.forwardTab.closeBtn.click();\n });\n } */\n\n window.removeEventListener('keydown', this.onKeyDown);\n\n promise.finally(() => {\n this.wholeDiv.remove();\n rootScope.overlayIsActive = false;\n animationIntersector.checkAnimations(false);\n });\n\n return promise;\n }\n\n onClick = (e: MouseEvent) => {\n if(this.setMoverAnimationPromise) return;\n\n const target = e.target as HTMLElement;\n if(target.tagName === 'A') return;\n cancelEvent(e);\n\n if(isTouchSupported) {\n if(this.highlightSwitchersTimeout) {\n clearTimeout(this.highlightSwitchersTimeout);\n } else {\n this.wholeDiv.classList.add('highlight-switchers');\n }\n\n this.highlightSwitchersTimeout = window.setTimeout(() => {\n this.wholeDiv.classList.remove('highlight-switchers');\n this.highlightSwitchersTimeout = 0;\n }, 3e3);\n \n return;\n }\n\n let mover: HTMLElement = null;\n ['media-viewer-mover', 'media-viewer-buttons', 'media-viewer-author', 'media-viewer-caption'].find(s => {\n try {\n mover = findUpClassName(target, s);\n if(mover) return true;\n } catch(err) {return false;}\n });\n\n if(/* target === this.mediaViewerDiv */!mover || target.tagName === 'IMG' || target.tagName === 'image') {\n this.buttons.close.click();\n }\n };\n\n private onKeyDown = (e: KeyboardEvent) => {\n //this.log('onKeyDown', e);\n \n if(e.key === 'ArrowRight') {\n this.buttons.next.click();\n } else if(e.key === 'ArrowLeft') {\n this.buttons.prev.click();\n }\n };\n\n protected async setMoverToTarget(target: HTMLElement, closing = false, fromRight = 0) {\n const mover = this.content.mover;\n\n if(!closing) {\n mover.innerHTML = '';\n //mover.append(this.buttons.prev, this.buttons.next);\n }\n \n this.removeCenterFromMover(mover);\n\n const wasActive = fromRight !== 0;\n\n const delay = rootScope.settings.animationsEnabled ? (wasActive ? 350 : 200) : 0;\n //let delay = wasActive ? 350 : 10000;\n\n /* if(wasActive) {\n this.moveTheMover(mover);\n mover = this.setNewMover();\n } */\n\n /* if(DEBUG) {\n this.log('setMoverToTarget', target, closing, wasActive, fromRight);\n } */\n\n let realParent: HTMLElement;\n\n let rect: DOMRect;\n if(target) {\n if(target instanceof AvatarElement || target.classList.contains('grid-item')) {\n realParent = target;\n rect = target.getBoundingClientRect();\n } else if(target instanceof SVGImageElement || target.parentElement instanceof SVGForeignObjectElement) {\n realParent = findUpClassName(target, 'attachment');\n rect = realParent.getBoundingClientRect();\n } else if(target.classList.contains('profile-avatars-avatar')) {\n realParent = findUpClassName(target, 'profile-avatars-container');\n rect = realParent.getBoundingClientRect();\n\n // * if not active avatar\n if(closing && target.getBoundingClientRect().left !== rect.left) {\n target = realParent = rect = undefined;\n }\n }\n }\n\n if(!target) {\n target = this.content.media;\n }\n\n if(!rect) {\n realParent = target.parentElement as HTMLElement;\n rect = target.getBoundingClientRect();\n }\n\n let needOpacity = false;\n if(target !== this.content.media && !target.classList.contains('profile-avatars-avatar')) {\n const overflowElement = findUpClassName(realParent, 'scrollable');\n const visibleRect = getVisibleRect(realParent, overflowElement);\n\n if(closing && (!visibleRect || visibleRect.overflow.vertical === 2 || visibleRect.overflow.horizontal === 2)) {\n target = this.content.media;\n realParent = target.parentElement as HTMLElement;\n rect = target.getBoundingClientRect();\n } else if(visibleRect && (visibleRect.overflow.vertical === 1 || visibleRect.overflow.horizontal === 1)) {\n needOpacity = true;\n }\n }\n\n const containerRect = this.content.media.getBoundingClientRect();\n \n let transform = '';\n let left: number;\n let top: number;\n\n if(wasActive) {\n left = fromRight === 1 ? appPhotosManager.windowW : -containerRect.width;\n top = containerRect.top;\n } else {\n left = rect.left;\n top = rect.top;\n }\n\n transform += `translate3d(${left}px,${top}px,0) `;\n\n /* if(wasActive) {\n left = fromRight === 1 ? appPhotosManager.windowW / 2 : -(containerRect.width + appPhotosManager.windowW / 2);\n transform += `translate(${left}px,-50%) `;\n } else {\n left = rect.left - (appPhotosManager.windowW / 2);\n top = rect.top - (appPhotosManager.windowH / 2);\n transform += `translate(${left}px,${top}px) `;\n } */\n\n let aspecter: HTMLDivElement;\n if(target instanceof HTMLImageElement || target instanceof HTMLVideoElement || target.tagName === 'DIV') {\n if(mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter')) {\n aspecter = mover.firstElementChild as HTMLDivElement;\n\n const player = aspecter.querySelector('.ckin__player');\n if(player) {\n const video = player.firstElementChild as HTMLVideoElement;\n aspecter.append(video);\n player.remove();\n }\n\n if(!aspecter.style.cssText) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать\n mover.classList.remove('active');\n this.setFullAspect(aspecter, containerRect, rect);\n void mover.offsetLeft; // reflow\n mover.classList.add('active');\n }\n } else {\n aspecter = document.createElement('div');\n aspecter.classList.add('media-viewer-aspecter'/* , 'disable-hover' */);\n mover.prepend(aspecter);\n }\n \n aspecter.style.cssText = `width: ${rect.width}px; height: ${rect.height}px; transform: scale3d(${containerRect.width / rect.width}, ${containerRect.height / rect.height}, 1);`;\n }\n\n mover.style.width = containerRect.width + 'px';\n mover.style.height = containerRect.height + 'px';\n\n const scaleX = rect.width / containerRect.width;\n const scaleY = rect.height / containerRect.height;\n if(!wasActive) {\n transform += `scale3d(${scaleX},${scaleY},1) `;\n }\n\n let borderRadius = window.getComputedStyle(realParent).getPropertyValue('border-radius');\n const brSplitted = fillPropertyValue(borderRadius) as string[];\n borderRadius = brSplitted.map(r => (parseInt(r) / scaleX) + 'px').join(' ');\n if(!wasActive) {\n mover.style.borderRadius = borderRadius;\n }\n //let borderRadius = '0px 0px 0px 0px';\n\n mover.style.transform = transform;\n\n needOpacity && (mover.style.opacity = '0'/* !closing ? '0' : '' */);\n\n /* if(wasActive) {\n this.log('setMoverToTarget', mover.style.transform);\n } */\n\n let path: SVGPathElement;\n const isOut = target.classList.contains('is-out');\n\n const deferred = this.setMoverAnimationPromise = deferredPromise<void>();\n const ret = {onAnimationEnd: deferred};\n\n this.setMoverAnimationPromise.then(() => {\n this.setMoverAnimationPromise = null;\n });\n\n if(!closing) {\n let mediaElement: HTMLImageElement | HTMLVideoElement;\n let src: string;\n\n if(target.tagName === 'DIV' || target.tagName === 'AVATAR-ELEMENT') { // useContainerAsTarget\n if(target.firstElementChild) {\n mediaElement = new Image();\n src = (target.firstElementChild as HTMLImageElement).src;\n mover.append(mediaElement);\n }\n /* mediaElement = new Image();\n src = target.style.backgroundImage.slice(5, -2); */\n \n } else if(target instanceof HTMLImageElement) {\n mediaElement = new Image();\n src = target.src;\n } else if(target instanceof HTMLVideoElement) {\n const video = mediaElement = document.createElement('video');\n video.src = target?.src;\n } else if(target instanceof SVGSVGElement) {\n const clipId = target.dataset.clipId;\n const newClipId = clipId + '-mv';\n\n const {width, height} = containerRect;\n\n const newSvg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n newSvg.setAttributeNS(null, 'width', '' + width);\n newSvg.setAttributeNS(null, 'height', '' + height);\n\n // нижние два свойства для масштабирования\n newSvg.setAttributeNS(null, 'viewBox', `0 0 ${width} ${height}`);\n newSvg.setAttributeNS(null, 'preserveAspectRatio', 'xMidYMid meet');\n\n newSvg.insertAdjacentHTML('beforeend', target.firstElementChild.outerHTML.replace(clipId, newClipId));\n newSvg.insertAdjacentHTML('beforeend', target.lastElementChild.outerHTML.replace(clipId, newClipId));\n\n // теперь надо выставить новую позицию для хвостика\n const defs = newSvg.firstElementChild;\n const use = defs.firstElementChild.firstElementChild as SVGUseElement;\n if(use instanceof SVGUseElement) {\n let transform = use.getAttributeNS(null, 'transform');\n transform = transform.replace(/translate\\((.+?), (.+?)\\) scale\\((.+?), (.+?)\\)/, (match, x, y, sX, sY) => {\n x = +x;\n if(x !== 2) {\n x = width - (2 / scaleX);\n } else {\n x = 2 / scaleX;\n }\n \n y = height;\n \n return `translate(${x}, ${y}) scale(${+sX / scaleX}, ${+sY / scaleY})`;\n });\n use.setAttributeNS(null, 'transform', transform);\n \n // и новый RECT\n path = defs.firstElementChild.lastElementChild as SVGPathElement;\n\n // код ниже нужен только чтобы скрыть моргание до момента как сработает таймаут\n let d: string;\n const br: [number, number, number, number] = borderRadius.split(' ').map(v => parseInt(v)) as any;\n if(isOut) d = generatePathData(0, 0, width - 9 / scaleX, height, ...br);\n else d = generatePathData(9 / scaleX, 0, width - 9 / scaleX, height, ...br);\n path.setAttributeNS(null, 'd', d);\n }\n\n const foreignObject = newSvg.lastElementChild;\n foreignObject.setAttributeNS(null, 'width', '' + containerRect.width);\n foreignObject.setAttributeNS(null, 'height', '' + containerRect.height);\n \n mover.prepend(newSvg);\n }\n\n if(aspecter) {\n aspecter.style.borderRadius = borderRadius;\n\n if(mediaElement) {\n aspecter.append(mediaElement);\n }\n }\n\n mediaElement = mover.querySelector('video, img');\n if(mediaElement instanceof HTMLImageElement) {\n mediaElement.classList.add('thumbnail');\n if(!aspecter) {\n mediaElement.style.width = containerRect.width + 'px';\n mediaElement.style.height = containerRect.height + 'px';\n }\n\n if(src) {\n await new Promise((resolve, reject) => {\n mediaElement.addEventListener('load', resolve);\n \n if(src) {\n mediaElement.src = src;\n }\n });\n }\n }/* else if(mediaElement instanceof HTMLVideoElement && mediaElement.firstElementChild && ((mediaElement.firstElementChild as HTMLSourceElement).src || src)) {\n await new Promise((resolve, reject) => {\n mediaElement.addEventListener('loadeddata', resolve);\n\n if(src) {\n (mediaElement.firstElementChild as HTMLSourceElement).src = src;\n }\n });\n } */\n \n mover.style.display = '';\n\n window.requestAnimationFrame(() => {\n mover.classList.add(wasActive ? 'moving' : 'active');\n });\n } else {\n /* if(mover.classList.contains('center')) {\n mover.classList.remove('center');\n void mover.offsetLeft; // reflow\n } */\n \n if(target instanceof SVGSVGElement) {\n path = mover.querySelector('path');\n\n if(path) {\n this.sizeTailPath(path, containerRect, scaleX, delay, false, isOut, borderRadius);\n }\n }\n\n if(target.classList.contains('media-viewer-media')) {\n mover.classList.add('hiding');\n }\n\n setTimeout(() => {\n this.wholeDiv.classList.remove('active');\n }, 0);\n\n setTimeout(() => {\n mover.style.borderRadius = borderRadius;\n\n if(mover.firstElementChild) {\n (mover.firstElementChild as HTMLElement).style.borderRadius = borderRadius;\n }\n }, delay / 2);\n\n setTimeout(() => {\n mover.innerHTML = '';\n mover.classList.remove('moving', 'active', 'hiding');\n mover.style.cssText = 'display: none;';\n\n deferred.resolve();\n }, delay);\n\n return ret;\n }\n\n mover.classList.toggle('opening', !closing);\n\n //await new Promise((resolve) => setTimeout(resolve, 0));\n //await new Promise((resolve) => window.requestAnimationFrame(resolve));\n // * одного RAF'а недостаточно, иногда анимация с одним не срабатывает (преимущественно на мобильных)\n await new Promise((resolve) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));\n\n // чтобы проверить установленную позицию - раскомментировать\n // throw '';\n\n //await new Promise((resolve) => setTimeout(resolve, 5e3));\n\n mover.style.transform = `translate3d(${containerRect.left}px,${containerRect.top}px,0) scale3d(1,1,1)`;\n //mover.style.transform = `translate(-50%,-50%) scale(1,1)`;\n needOpacity && (mover.style.opacity = ''/* closing ? '0' : '' */);\n\n if(aspecter) {\n this.setFullAspect(aspecter, containerRect, rect);\n }\n\n //throw '';\n\n setTimeout(() => {\n mover.style.borderRadius = '';\n\n if(mover.firstElementChild) {\n (mover.firstElementChild as HTMLElement).style.borderRadius = '';\n }\n }, 0/* delay / 2 */);\n\n mover.dataset.timeout = '' + setTimeout(() => {\n mover.classList.remove('moving');\n\n if(aspecter) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать\n if(mover.querySelector('video') || true) {\n mover.classList.remove('active');\n aspecter.style.cssText = '';\n void mover.offsetLeft; // reflow\n }\n \n //aspecter.classList.remove('disable-hover');\n }\n\n // эти строки нужны для установки центральной позиции, в случае ресайза это будет нужно\n mover.classList.add('center', 'no-transition');\n /* mover.style.left = mover.style.top = '50%';\n mover.style.transform = 'translate(-50%, -50%)';\n void mover.offsetLeft; // reflow */\n\n // это уже нужно для будущих анимаций\n mover.classList.add('active');\n delete mover.dataset.timeout;\n\n deferred.resolve();\n }, delay);\n\n if(path) {\n this.sizeTailPath(path, containerRect, scaleX, delay, true, isOut, borderRadius);\n }\n\n return ret;\n }\n\n protected setFullAspect(aspecter: HTMLDivElement, containerRect: DOMRect, rect: DOMRect) {\n /* let media = aspecter.firstElementChild;\n let proportion: number;\n if(media instanceof HTMLImageElement) {\n proportion = media.naturalWidth / media.naturalHeight;\n } else if(media instanceof HTMLVideoElement) {\n proportion = media.videoWidth / media.videoHeight;\n } */\n const proportion = containerRect.width / containerRect.height;\n\n let {width, height} = rect;\n /* if(proportion === 1) {\n aspecter.style.cssText = '';\n } else { */\n if(proportion > 0) {\n width = height * proportion;\n } else {\n height = width * proportion;\n }\n\n //this.log('will set style aspecter:', `width: ${width}px; height: ${height}px; transform: scale(${containerRect.width / width}, ${containerRect.height / height});`);\n\n aspecter.style.cssText = `width: ${width}px; height: ${height}px; transform: scale3d(${containerRect.width / width}, ${containerRect.height / height}, 1);`;\n //}\n }\n\n protected sizeTailPath(path: SVGPathElement, rect: DOMRect, scaleX: number, delay: number, upscale: boolean, isOut: boolean, borderRadius: string) {\n const start = Date.now();\n const {width, height} = rect;\n delay = delay / 2;\n\n const br = borderRadius.split(' ').map(v => parseInt(v));\n\n const step = () => {\n const diff = Date.now() - start;\n\n let progress = delay ? diff / delay : 1;\n if(progress > 1) progress = 1;\n if(upscale) progress = 1 - progress;\n\n const _br: [number, number, number, number] = br.map(v => v * progress) as any;\n\n let d: string;\n if(isOut) d = generatePathData(0, 0, width - (9 / scaleX * progress), height, ..._br);\n else d = generatePathData(9 / scaleX * progress, 0, width/* width - (9 / scaleX * progress) */, height, ..._br);\n path.setAttributeNS(null, 'd', d);\n\n if(diff < delay) window.requestAnimationFrame(step);\n };\n \n //window.requestAnimationFrame(step);\n step();\n }\n\n protected removeCenterFromMover(mover: HTMLElement) {\n if(mover.classList.contains('center')) {\n //const rect = mover.getBoundingClientRect();\n const rect = this.content.media.getBoundingClientRect();\n mover.style.transform = `translate3d(${rect.left}px,${rect.top}px,0)`;\n mover.classList.remove('center');\n void mover.offsetLeft; // reflow\n mover.classList.remove('no-transition');\n }\n }\n\n protected moveTheMover(mover: HTMLElement, toLeft = true) {\n const windowW = appPhotosManager.windowW;\n\n this.removeCenterFromMover(mover);\n\n //mover.classList.remove('active');\n mover.classList.add('moving');\n\n if(mover.dataset.timeout) { // и это тоже всё из-за скейла видео, так бы это не нужно было\n clearTimeout(+mover.dataset.timeout);\n }\n\n const rect = mover.getBoundingClientRect();\n\n const newTransform = mover.style.transform.replace(/translate3d\\((.+?),/, (match, p1) => {\n const x = toLeft ? -rect.width : windowW;\n //const x = toLeft ? -(rect.right + (rect.width / 2)) : windowW / 2;\n\n return match.replace(p1, x + 'px');\n });\n\n ////////this.log('set newTransform:', newTransform, mover.style.transform, toLeft);\n mover.style.transform = newTransform;\n\n setTimeout(() => {\n mover.remove();\n }, 350);\n }\n\n protected setNewMover() {\n const newMover = document.createElement('div');\n newMover.classList.add('media-viewer-mover');\n\n if(this.content.mover) {\n const oldMover = this.content.mover;\n oldMover.parentElement.append(newMover);\n } else {\n this.wholeDiv.append(newMover);\n }\n\n return this.content.mover = newMover;\n }\n\n /* public isElementVisible(container: HTMLElement, target: HTMLElement) {\n const rect = container.getBoundingClientRect();\n const targetRect = target.getBoundingClientRect();\n\n return targetRect.bottom > rect.top && targetRect.top < rect.bottom;\n } */\n\n protected updateMediaSource(target: HTMLElement, url: string, tagName: 'video' | 'img') {\n //if(target instanceof SVGSVGElement) {\n const el = target.tagName.toLowerCase() === tagName ? target : target.querySelector(tagName) as HTMLElement;\n if(el) {\n renderImageFromUrl(el, url);\n }\n /* } else {\n\n } */\n }\n\n protected setAuthorInfo(fromId: number, timestamp: number) {\n const date = new Date();\n const time = new Date(timestamp * 1000);\n const now = date.getTime() / 1000;\n\n const timeStr = time.getHours() + ':' + ('0' + time.getMinutes()).slice(-2);\n let dateStr: string;\n if((now - timestamp) < ONE_DAY && date.getDate() === time.getDate()) { // if the same day\n dateStr = 'Today';\n } else if((now - timestamp) < (ONE_DAY * 2) && (date.getDate() - 1) === time.getDate()) { // yesterday\n dateStr = 'Yesterday';\n } else if(date.getFullYear() !== time.getFullYear()) { // different year\n dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate() + ', ' + time.getFullYear();\n } else {\n dateStr = months[time.getMonth()].slice(0, 3) + ' ' + time.getDate();\n }\n\n this.author.date.innerText = dateStr + ' at ' + timeStr;\n\n const name = appPeersManager.getPeerTitle(fromId);\n this.author.nameEl.innerHTML = name;\n\n let oldAvatar = this.author.avatarEl;\n this.author.avatarEl = (this.author.avatarEl.cloneNode() as AvatarElement);\n this.author.avatarEl.setAttribute('peer', '' + fromId);\n oldAvatar.parentElement.replaceChild(this.author.avatarEl, oldAvatar);\n }\n \n protected async _openMedia(media: any, timestamp: number, fromId: number, fromRight: number, target?: HTMLElement, reverse = false, \n prevTargets: TargetType[] = [], nextTargets: TargetType[] = [], needLoadMore = true) {\n if(this.setMoverPromise) return this.setMoverPromise;\n\n /* if(DEBUG) {\n this.log('openMedia:', media, fromId, prevTargets, nextTargets);\n } */\n\n this.setAuthorInfo(fromId, timestamp);\n \n const isVideo = (media as MyDocument).type === 'video' || (media as MyDocument).type === 'gif';\n\n if(this.isFirstOpen) {\n //this.targetContainer = targetContainer;\n this.prevTargets = prevTargets;\n this.nextTargets = nextTargets;\n this.reverse = reverse;\n this.needLoadMore = needLoadMore;\n this.isFirstOpen = false;\n //this.loadMore = loadMore;\n\n /* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) {\n appSidebarRight.forwardTab.closeBtn.click();\n await new Promise((resolve) => setTimeout(resolve, 200));\n } */\n }\n\n /* if(this.nextTargets.length < 10 && this.loadMore) {\n this.loadMore();\n } */\n\n //if(prevTarget && (!prevTarget.parentElement || !this.isElementVisible(this.targetContainer, prevTarget))) prevTarget = null;\n //if(nextTarget && (!nextTarget.parentElement || !this.isElementVisible(this.targetContainer, nextTarget))) nextTarget = null;\n\n this.buttons.prev.classList.toggle('hide', !this.prevTargets.length);\n this.buttons.next.classList.toggle('hide', !this.nextTargets.length);\n \n const container = this.content.media;\n const useContainerAsTarget = !target || target === container;\n if(useContainerAsTarget) target = container;\n\n this.lastTarget = target;\n const tempId = ++this.tempId;\n\n if(this.needLoadMore) {\n if(this.nextTargets.length < 20) {\n this.loadMoreMedia(!this.reverse);\n }\n \n if(this.prevTargets.length < 20) {\n this.loadMoreMedia(this.reverse);\n }\n }\n \n if(container.firstElementChild) {\n container.innerHTML = '';\n }\n \n // ok set\n\n const wasActive = fromRight !== 0;\n if(wasActive) {\n this.moveTheMover(this.content.mover, fromRight === 1);\n this.setNewMover();\n } else {\n window.addEventListener('keydown', this.onKeyDown);\n const mainColumns = this.pageEl.querySelector('#main-columns');\n this.pageEl.insertBefore(this.wholeDiv, mainColumns);\n void this.wholeDiv.offsetLeft; // reflow\n this.wholeDiv.classList.add('active');\n rootScope.overlayIsActive = true;\n animationIntersector.checkAnimations(true);\n\n if(!isMobileSafari) {\n appNavigationController.pushItem({\n type: 'media',\n onPop: (canAnimate) => {\n if(this.setMoverAnimationPromise) {\n return false;\n }\n \n this.close();\n }\n });\n }\n }\n\n ////////this.log('wasActive:', wasActive);\n\n const mover = this.content.mover;\n\n //const maxWidth = appPhotosManager.windowW - 16;\n const maxWidth = mediaSizes.isMobile ? this.pageEl.scrollWidth : this.pageEl.scrollWidth - 16;\n const maxHeight = appPhotosManager.windowH - 100;\n let thumbPromise: Promise<any> = Promise.resolve();\n if(useContainerAsTarget) {\n const cacheContext = appPhotosManager.getCacheContext(media);\n let img: HTMLImageElement;\n if(cacheContext.downloaded) {\n img = new Image();\n img.src = cacheContext.url;\n } else {\n const gotThumb = appPhotosManager.getStrippedThumbIfNeeded(media, true);\n if(gotThumb) {\n thumbPromise = gotThumb.loadPromise;\n img = gotThumb.image;\n }\n }\n\n if(img) {\n img.classList.add('thumbnail');\n container.append(img);\n }\n }\n const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true);\n\n // need after setAttachmentSize\n /* if(useContainerAsTarget) {\n target = target.querySelector('img, video') || target;\n } */\n\n const preloader = media.supportsStreaming ? this.preloaderStreamable : this.preloader;\n\n let setMoverPromise: Promise<void>;\n if(isVideo) {\n ////////this.log('will wrap video', media, size);\n\n // потому что для safari нужно создать элемент из event'а\n const video = document.createElement('video');\n\n const set = () => this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => {\n //return; // set and don't move\n //if(wasActive) return;\n //return;\n \n const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover;\n //const video = mover.querySelector('video') || document.createElement('video');\n \n const moverVideo = mover.querySelector('video');\n if(moverVideo) {\n moverVideo.remove();\n }\n \n //video.src = '';\n \n video.setAttribute('playsinline', 'true');\n \n // * fix for playing video if viewer is closed (https://contest.com/javascript-web-bonus/entry1425#issue11629)\n video.addEventListener('timeupdate', () => {\n if(this.tempId !== tempId) {\n video.pause();\n }\n });\n \n if(isSafari) {\n // test stream\n // video.controls = true;\n video.autoplay = true;\n }\n \n if(media.type === 'gif') {\n video.muted = true;\n video.autoplay = true;\n video.loop = true;\n }\n \n if(!video.parentElement) {\n div.append(video);\n }\n \n const canPlayThrough = new Promise((resolve) => {\n video.addEventListener('canplay', resolve, {once: true});\n });\n \n const createPlayer = () => {\n if(media.type !== 'gif') {\n video.dataset.ckin = 'default';\n video.dataset.overlay = '1';\n \n // fix for simultaneous play\n appMediaPlaybackController.pause();\n appMediaPlaybackController.willBePlayedMedia = null;\n \n Promise.all([canPlayThrough, onAnimationEnd]).then(() => {\n if(this.tempId !== tempId) {\n return;\n }\n \n const player = new VideoPlayer(video, true, media.supportsStreaming);\n /* div.append(video);\n mover.append(player.wrapper); */\n });\n }\n };\n \n if(media.supportsStreaming) {\n onAnimationEnd.then(() => {\n if(video.readyState < video.HAVE_FUTURE_DATA) {\n preloader.attach(mover, true);\n }\n \n /* canPlayThrough.then(() => {\n preloader.detach();\n }); */\n });\n \n const attachCanPlay = () => {\n video.addEventListener('canplay', () => {\n //this.log('video waited and progress loaded');\n preloader.detach();\n video.parentElement.classList.remove('is-buffering');\n }, {once: true});\n };\n \n video.addEventListener('waiting', (e) => {\n const loading = video.networkState === video.NETWORK_LOADING;\n const isntEnoughData = video.readyState < video.HAVE_FUTURE_DATA;\n \n //this.log('video waiting for progress', loading, isntEnoughData);\n if(loading && isntEnoughData) {\n attachCanPlay();\n \n preloader.attach(mover, true);\n \n // поставлю класс для плеера, чтобы убрать большую иконку пока прелоадер на месте\n video.parentElement.classList.add('is-buffering');\n }\n });\n \n attachCanPlay();\n }\n \n //if(!video.src || media.url !== video.src) {\n const load = () => {\n const promise = media.supportsStreaming ? Promise.resolve() : appDocsManager.downloadDoc(media);\n \n if(!media.supportsStreaming) {\n onAnimationEnd.then(() => {\n if(!media.url) {\n preloader.attach(mover, true, promise);\n }\n });\n }\n \n (promise as Promise<any>).then(async() => {\n if(this.tempId !== tempId) {\n this.log.warn('media viewer changed video');\n return;\n }\n \n const url = media.url;\n if(target instanceof SVGSVGElement/* && (video.parentElement || !isSafari) */) { // if video exists\n //if(!video.parentElement) {\n div.firstElementChild.lastElementChild.append(video);\n //}\n \n this.updateMediaSource(mover, url, 'video');\n } else {\n renderImageFromUrl(video, url);\n }\n \n createPlayer();\n });\n \n return promise;\n };\n \n this.lazyLoadQueue.unshift({load});\n //} else createPlayer();\n });\n\n setMoverPromise = thumbPromise.then(set);\n } else {\n const set = () => this.setMoverToTarget(target, false, fromRight).then(({onAnimationEnd}) => {\n //return; // set and don't move\n //if(wasActive) return;\n //return;\n \n const load = () => {\n const cancellablePromise = appPhotosManager.preloadPhoto(media.id, size);\n \n onAnimationEnd.then(() => {\n if(!media.url) {\n this.preloader.attachPromise(cancellablePromise);\n //this.preloader.attach(mover, true, cancellablePromise);\n }\n });\n \n Promise.all([onAnimationEnd, cancellablePromise]).then(() => {\n if(this.tempId !== tempId) {\n this.log.warn('media viewer changed photo');\n return;\n }\n \n ///////this.log('indochina', blob);\n \n const url = media.url;\n if(target instanceof SVGSVGElement) {\n this.updateMediaSource(target, url, 'img');\n this.updateMediaSource(mover, url, 'img');\n \n if(mediaSizes.isMobile) {\n const imgs = mover.querySelectorAll('img');\n if(imgs && imgs.length) {\n imgs.forEach(img => {\n img.classList.remove('thumbnail'); // может здесь это вообще не нужно\n });\n }\n }\n } else {\n const div = mover.firstElementChild && mover.firstElementChild.classList.contains('media-viewer-aspecter') ? mover.firstElementChild : mover;\n const haveImage = div.firstElementChild?.tagName === 'IMG' ? div.firstElementChild as HTMLImageElement : null;\n if(!haveImage || haveImage.src !== url) {\n let image = new Image();\n image.classList.add('thumbnail');\n \n //this.log('will renderImageFromUrl:', image, div, target);\n \n renderImageFromUrl(image, url, () => {\n this.updateMediaSource(target, url, 'img');\n \n if(haveImage) {\n window.requestAnimationFrame(() => {\n haveImage.remove();\n });\n }\n \n div.append(image);\n });\n }\n }\n \n //this.preloader.detach();\n }).catch(err => {\n this.log.error(err);\n this.preloader.attach(mover);\n this.preloader.setManual();\n });\n \n return cancellablePromise;\n };\n \n this.lazyLoadQueue.unshift({load});\n });\n\n setMoverPromise = thumbPromise.then(set);\n }\n\n return this.setMoverPromise = setMoverPromise.catch(() => {\n this.setMoverAnimationPromise = null;\n }).finally(() => {\n this.setMoverPromise = null;\n });\n }\n}\n\ntype AppMediaViewerTargetType = {\n element: HTMLElement,\n mid: number,\n peerId: number\n};\nexport default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delete' | 'forward', AppMediaViewerTargetType> {\n public currentMessageId = 0;\n public currentPeerId = 0;\n public searchContext: SearchSuperContext;\n\n constructor() {\n super(['delete', 'forward']);\n\n /* const stub = document.createElement('div');\n stub.classList.add(MEDIA_VIEWER_CLASSNAME + '-stub');\n this.content.main.prepend(stub); */\n\n this.content.caption = document.createElement('div');\n this.content.caption.classList.add(MEDIA_VIEWER_CLASSNAME + '-caption'/* , 'media-viewer-stub' */);\n\n new Scrollable(this.content.caption);\n\n //this.content.main.append(this.content.caption);\n this.wholeDiv.append(this.content.caption);\n\n this.setBtnMenuToggle([{\n icon: 'forward',\n text: 'Forward',\n onClick: this.onForwardClick\n }, {\n icon: 'download',\n text: 'MediaViewer.Context.Download',\n onClick: this.onDownloadClick\n }, {\n icon: 'delete danger btn-disabled',\n text: 'Delete',\n onClick: () => {}\n }]);\n\n // * constructing html end\n \n this.setListeners();\n }\n\n protected setListeners() {\n super.setListeners();\n this.buttons.forward.addEventListener('click', this.onForwardClick);\n this.author.container.addEventListener('click', this.onAuthorClick);\n }\n\n /* public close(e?: MouseEvent) {\n const good = !this.setMoverAnimationPromise;\n const promise = super.close(e);\n\n if(good) { // clear\n this.currentMessageId = 0;\n this.peerId = 0;\n }\n\n return promise;\n } */\n\n onPrevClick = (target: AppMediaViewerTargetType) => {\n this.nextTargets.unshift({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId});\n this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, -1);\n };\n\n onNextClick = (target: AppMediaViewerTargetType) => {\n this.prevTargets.push({element: this.lastTarget, mid: this.currentMessageId, peerId: this.currentPeerId});\n this.openMedia(appMessagesManager.getMessageByPeer(target.peerId, target.mid), target.element, 1);\n };\n\n onForwardClick = () => {\n if(this.currentMessageId) {\n //appSidebarRight.forwardTab.open([this.currentMessageId]);\n new PopupForward(this.currentPeerId, [this.currentMessageId], () => {\n return this.close();\n });\n }\n };\n\n onAuthorClick = (e: MouseEvent) => {\n if(this.currentMessageId && this.currentMessageId !== Number.MAX_SAFE_INTEGER) {\n const mid = this.currentMessageId;\n const peerId = this.currentPeerId;\n const threadId = this.searchContext.threadId;\n this.close(e)\n //.then(() => mediaSizes.isMobile ? appSidebarRight.sharedMediaTab.closeBtn.click() : Promise.resolve())\n .then(() => {\n if(mediaSizes.isMobile) {\n const tab = appSidebarRight.getTab(AppSharedMediaTab);\n if(tab) {\n tab.close();\n }\n }\n\n const message = appMessagesManager.getMessageByPeer(peerId, mid);\n appImManager.setInnerPeer(message.peerId, mid, threadId ? 'discussion' : undefined, threadId);\n });\n }\n };\n\n onDownloadClick = () => {\n const message = appMessagesManager.getMessageByPeer(this.currentPeerId, this.currentMessageId);\n if(message.media.photo) {\n appPhotosManager.savePhotoFile(message.media.photo, appImManager.chat.bubbles.lazyLoadQueue.queueId);\n } else {\n let document: MyDocument = null;\n\n if(message.media.webpage) document = message.media.webpage.document;\n else document = message.media.document;\n\n if(document) {\n //console.log('will save document:', document);\n appDocsManager.saveDocFile(document, appImManager.chat.bubbles.lazyLoadQueue.queueId);\n }\n }\n };\n\n // нет смысла делать проверку для reverse и loadMediaPromise\n protected loadMoreMedia = (older = true) => {\n //if(!older && this.reverse) return;\n\n if(older && this.loadedAllMediaDown) return Promise.resolve();\n else if(!older && this.loadedAllMediaUp) return Promise.resolve();\n\n if(older && this.loadMediaPromiseDown) return this.loadMediaPromiseDown;\n else if(!older && this.loadMediaPromiseUp) return this.loadMediaPromiseUp;\n\n const loadCount = 50;\n const backLimit = older ? 0 : loadCount;\n let maxId = this.currentMessageId;\n \n let anchor: AppMediaViewerTargetType;\n if(older) {\n anchor = this.reverse ? this.prevTargets[0] : this.nextTargets[this.nextTargets.length - 1];\n } else {\n anchor = this.reverse ? this.nextTargets[this.nextTargets.length - 1] : this.prevTargets[0];\n }\n\n if(anchor) maxId = anchor.mid;\n if(!older) maxId = appMessagesManager.incrementMessageId(maxId, 1);\n\n const promise = appMessagesManager.getSearch({\n peerId: this.searchContext.peerId,\n query: this.searchContext.query,\n inputFilter: {\n _: this.searchContext.inputFilter\n },\n maxId,\n limit: backLimit ? 0 : loadCount,\n backLimit,\n threadId: this.searchContext.threadId,\n folderId: this.searchContext.folderId,\n nextRate: this.searchContext.nextRate,\n minDate: this.searchContext.minDate,\n maxDate: this.searchContext.maxDate\n }).then(value => {\n if(DEBUG) {\n this.log('loaded more media by maxId:', maxId, value, older, this.reverse);\n }\n\n if(value.next_rate) {\n this.searchContext.nextRate = value.next_rate;\n }\n\n if(value.history.length < loadCount) {\n /* if(this.reverse) {\n if(older) this.loadedAllMediaUp = true;\n else this.loadedAllMediaDown = true;\n } else { */\n if(older) this.loadedAllMediaDown = true;\n else this.loadedAllMediaUp = true;\n //}\n }\n\n const method: any = older ? value.history.forEach.bind(value.history) : forEachReverse.bind(null, value.history);\n method((message: Message.message) => {\n const {mid, peerId} = message;\n const media = this.getMediaFromMessage(message);\n\n if(!media) return;\n //if(media._ === 'document' && media.type !== 'video') return;\n\n const t = {element: null as HTMLElement, mid, peerId};\n if(older) {\n if(this.reverse) this.prevTargets.unshift(t);\n else this.nextTargets.push(t);\n } else {\n if(this.reverse) this.nextTargets.push(t);\n else this.prevTargets.unshift(t);\n }\n });\n\n this.buttons.prev.classList.toggle('hide', !this.prevTargets.length);\n this.buttons.next.classList.toggle('hide', !this.nextTargets.length);\n }, () => {}).then(() => {\n if(older) this.loadMediaPromiseDown = null;\n else this.loadMediaPromiseUp = null;\n });\n\n if(older) this.loadMediaPromiseDown = promise;\n else this.loadMediaPromiseUp = promise;\n\n return promise;\n };\n\n private getMediaFromMessage(message: any) {\n return message.action ? message.action.photo : message.media.photo \n || message.media.document \n || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo));\n }\n\n private setCaption(message: any) {\n const caption = message.message;\n this.content.caption.classList.toggle('hide', !caption);\n if(caption) {\n this.content.caption.firstElementChild.innerHTML = RichTextProcessor.wrapRichText(caption, {\n entities: message.totalEntities\n });\n } else {\n this.content.caption.firstElementChild.innerHTML = '';\n }\n }\n\n public setSearchContext(context: SearchSuperContext) {\n this.searchContext = context;\n\n if(this.searchContext.folderId !== undefined) {\n this.loadedAllMediaUp = true;\n\n if(this.searchContext.nextRate === undefined) {\n this.loadedAllMediaDown = true;\n }\n }\n\n return this;\n }\n\n public async openMedia(message: any, target?: HTMLElement, fromRight = 0, reverse = false, \n prevTargets: AppMediaViewer['prevTargets'] = [], nextTargets: AppMediaViewer['prevTargets'] = [], needLoadMore = true) {\n if(this.setMoverPromise) return this.setMoverPromise;\n\n const mid = message.mid;\n const fromId = message.fromId;\n const media = this.getMediaFromMessage(message);\n\n this.currentMessageId = mid;\n this.currentPeerId = message.peerId;\n const promise = super._openMedia(media, message.date, fromId, fromRight, target, reverse, prevTargets, nextTargets, needLoadMore);\n this.setCaption(message);\n\n return promise;\n }\n}\n\ntype AppMediaViewerAvatarTargetType = {element: HTMLElement, photoId: string};\nexport class AppMediaViewerAvatar extends AppMediaViewerBase<'', 'delete', AppMediaViewerAvatarTargetType> {\n public currentPhotoId: string;\n public peerId: number;\n\n constructor(peerId: number) {\n super(['delete']);\n\n this.peerId = peerId;\n\n this.setBtnMenuToggle([{\n icon: 'download',\n text: 'MediaViewer.Context.Download',\n onClick: this.onDownloadClick\n }, {\n icon: 'delete danger btn-disabled',\n text: 'Delete',\n onClick: () => {}\n }]);\n\n // * constructing html end\n \n this.setListeners();\n }\n\n onPrevClick = (target: AppMediaViewerAvatarTargetType) => {\n this.nextTargets.unshift({element: this.lastTarget, photoId: this.currentPhotoId});\n this.openMedia(target.photoId, target.element, -1);\n };\n\n onNextClick = (target: AppMediaViewerAvatarTargetType) => {\n this.prevTargets.push({element: this.lastTarget, photoId: this.currentPhotoId});\n this.openMedia(target.photoId, target.element, 1);\n };\n\n onDownloadClick = () => {\n appPhotosManager.savePhotoFile(appPhotosManager.getPhoto(this.currentPhotoId), appImManager.chat.bubbles.lazyLoadQueue.queueId);\n };\n\n protected loadMoreMedia = (older = true) => {\n if(this.peerId < 0) return Promise.resolve(); // ! это значит, что открыло аватар чата, но следующих фотографий нет.\n if(this.loadedAllMediaDown) return Promise.resolve();\n if(this.loadMediaPromiseDown) return this.loadMediaPromiseDown;\n\n const peerId = this.peerId;\n const loadCount = 50;\n\n const maxId = this.nextTargets.length ? this.nextTargets[this.nextTargets.length - 1].photoId : this.currentPhotoId;\n\n const promise = appPhotosManager.getUserPhotos(peerId, maxId, loadCount).then(value => {\n if(this.peerId !== peerId) {\n this.log.warn('peer changed');\n return;\n }\n\n // if(DEBUG) {\n // this.log('loaded more media by maxId:', /* maxId, */value, older, this.reverse);\n // }\n\n if(value.photos.length < loadCount) {\n this.loadedAllMediaDown = true;\n }\n\n value.photos.forEach(photoId => {\n if(this.currentPhotoId === photoId) return;\n this.nextTargets.push({element: null as HTMLElement, photoId: photoId});\n });\n\n this.buttons.prev.classList.toggle('hide', !this.prevTargets.length);\n this.buttons.next.classList.toggle('hide', !this.nextTargets.length);\n }, () => {}).then(() => {\n this.loadMediaPromiseDown = null;\n });\n\n return this.loadMediaPromiseDown = promise;\n };\n\n public async openMedia(photoId: string, target?: HTMLElement, fromRight = 0, prevTargets?: AppMediaViewerAvatarTargetType[], nextTargets?: AppMediaViewerAvatarTargetType[]) {\n if(this.setMoverPromise) return this.setMoverPromise;\n\n const photo = appPhotosManager.getPhoto(photoId);\n\n this.currentPhotoId = photo.id;\n \n return super._openMedia(photo, photo.date, this.peerId, fromRight, target, false, prevTargets, nextTargets);\n }\n}\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 getVisibleRect(element: HTMLElement, overflowElement: HTMLElement) {\r\n const rect = element.getBoundingClientRect();\r\n const overflowRect = overflowElement.getBoundingClientRect();\r\n\r\n let {top: overflowTop, bottom: overflowBottom} = overflowRect;\r\n\r\n // * respect sticky headers\r\n const sticky = overflowElement.querySelector('.sticky');\r\n if(sticky) {\r\n const stickyRect = sticky.getBoundingClientRect();\r\n overflowTop = stickyRect.bottom;\r\n }\r\n\r\n if(rect.top >= overflowBottom\r\n || rect.bottom <= overflowTop\r\n || rect.right <= overflowRect.left\r\n || rect.left >= overflowRect.right) {\r\n return null;\r\n }\r\n\r\n const overflow = {\r\n top: false,\r\n right: false,\r\n bottom: false,\r\n left: false,\r\n vertical: 0 as 0 | 1 | 2,\r\n horizontal: 0 as 0 | 1 | 2\r\n };\r\n\r\n // @ts-ignore\r\n const w: any = 'visualViewport' in window ? window.visualViewport : window;\r\n const windowWidth = w.width || w.innerWidth;\r\n const windowHeight = w.height || w.innerHeight;\r\n\r\n return {\r\n rect: {\r\n top: rect.top < overflowTop && overflowTop !== 0 ? (overflow.top = true, ++overflow.vertical, overflowTop) : rect.top,\r\n right: 0,\r\n bottom: rect.bottom > overflowBottom && overflowBottom !== windowHeight ? (overflow.bottom = true, ++overflow.vertical, overflowBottom) : rect.bottom,\r\n left: 0\r\n },\r\n overflow\r\n };\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appMessagesManager from \"../lib/appManagers/appMessagesManager\";\nimport appProfileManager from \"../lib/appManagers/appProfileManager\";\nimport rootScope from \"../lib/rootScope\";\nimport { attachClickEvent, cancelEvent } from \"../helpers/dom\";\nimport AppMediaViewer, { AppMediaViewerAvatar } from \"./appMediaViewer\";\nimport { Message, Photo } from \"../layer\";\nimport appPeersManager from \"../lib/appManagers/appPeersManager\";\nimport appPhotosManager from \"../lib/appManagers/appPhotosManager\";\n//import type { LazyLoadQueueIntersector } from \"./lazyLoadQueue\";\n\nconst onAvatarUpdate = (peerId: number) => {\n appProfileManager.removeFromAvatarsCache(peerId);\n (Array.from(document.querySelectorAll('avatar-element[peer=\"' + peerId + '\"]')) as AvatarElement[]).forEach(elem => {\n //console.log('updating avatar:', elem);\n elem.update();\n });\n};\n\nrootScope.on('avatar_update', onAvatarUpdate);\nrootScope.on('peer_title_edit', onAvatarUpdate);\n\nexport async function openAvatarViewer(target: HTMLElement, peerId: number, middleware: () => boolean, message?: any, prevTargets?: {element: HTMLElement, item: string | Message.messageService}[], nextTargets?: typeof prevTargets) {\n let photo = await appProfileManager.getFullPhoto(peerId);\n if(!middleware() || !photo) {\n return;\n }\n\n const getTarget = () => {\n const good = Array.from(target.querySelectorAll('img')).find(img => !img.classList.contains('emoji'));\n return good ? target : null;\n };\n\n if(peerId < 0) {\n const hadMessage = !!message;\n const inputFilter = 'inputMessagesFilterChatPhotos';\n if(!message) {\n message = await appMessagesManager.getSearch({\n peerId, \n inputFilter: {_: inputFilter}, \n maxId: 0, \n limit: 1 \n }).then(value => {\n //console.log(lol);\n // ! by descend\n return value.history[0];\n });\n\n if(!middleware()) {\n return;\n }\n }\n\n if(message) {\n // ! гений в деле, костылируем (но это гениально)\n const messagePhoto = message.action.photo;\n if(messagePhoto.id !== photo.id) {\n if(!hadMessage) {\n message = appMessagesManager.generateFakeAvatarMessage(peerId, photo);\n } else {\n \n }\n }\n\n const f = (arr: typeof prevTargets) => arr.map(el => ({\n element: el.element,\n mid: (el.item as Message.messageService).mid,\n peerId: (el.item as Message.messageService).peerId\n }));\n\n new AppMediaViewer()\n .setSearchContext({\n peerId,\n inputFilter,\n })\n .openMedia(message, getTarget(), undefined, undefined, prevTargets ? f(prevTargets) : undefined, nextTargets ? f(nextTargets) : undefined);\n\n return;\n }\n }\n\n if(photo) {\n if(typeof(message) === 'string') {\n photo = appPhotosManager.getPhoto(message);\n }\n \n const f = (arr: typeof prevTargets) => arr.map(el => ({\n element: el.element,\n photoId: el.item as string\n }));\n\n new AppMediaViewerAvatar(peerId).openMedia(photo.id, getTarget(), undefined, prevTargets ? f(prevTargets) : undefined, nextTargets ? f(nextTargets) : undefined);\n }\n}\n\nexport default class AvatarElement extends HTMLElement {\n private peerId: number;\n private isDialog = false;\n public peerTitle: string;\n public loadPromises: Promise<any>[];\n //public lazyLoadQueue: LazyLoadQueueIntersector;\n //private addedToQueue = false;\n\n constructor() {\n super();\n // элемент создан\n }\n\n connectedCallback() {\n // браузер вызывает этот метод при добавлении элемента в документ\n // (может вызываться много раз, если элемент многократно добавляется/удаляется)\n\n this.isDialog = !!this.getAttribute('dialog');\n if(this.getAttribute('clickable') === '') {\n this.setAttribute('clickable', 'set');\n let loading = false;\n attachClickEvent(this, async(e) => {\n cancelEvent(e);\n if(loading) return;\n //console.log('avatar clicked');\n const peerId = this.peerId;\n loading = true;\n await openAvatarViewer(this, this.peerId, () => this.peerId === peerId);\n loading = false;\n });\n }\n }\n\n /* disconnectedCallback() {\n // браузер вызывает этот метод при удалении элемента из документа\n // (может вызываться много раз, если элемент многократно добавляется/удаляется)\n if(this.lazyLoadQueue) {\n this.lazyLoadQueue.unobserve(this);\n }\n } */\n\n static get observedAttributes(): string[] {\n return ['peer', 'dialog', 'peer-title'/* массив имён атрибутов для отслеживания их изменений */];\n }\n\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n //console.log('avatar changed attribute:', name, oldValue, newValue);\n // вызывается при изменении одного из перечисленных выше атрибутов\n if(name === 'peer') {\n if(this.peerId === +newValue) {\n return;\n }\n \n this.peerId = appPeersManager.getPeerMigratedTo(+newValue) || +newValue;\n this.update();\n } else if(name === 'peer-title') {\n this.peerTitle = newValue;\n } else if(name === 'dialog') {\n this.isDialog = !!+newValue;\n }\n }\n\n public update() {\n /* if(this.lazyLoadQueue) {\n if(this.addedToQueue) return;\n this.lazyLoadQueue.push({\n div: this, \n load: () => {\n return appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle).finally(() => {\n this.addedToQueue = false;\n });\n }\n });\n this.addedToQueue = true;\n } else { */\n const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle);\n if(this.loadPromises && res && res.cached) {\n this.loadPromises.push(res.loadPromise);\n res.loadPromise.finally(() => {\n this.loadPromises = undefined;\n });\n }\n //}\n }\n}\n\ncustomElements.define(\"avatar-element\", AvatarElement);\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport appDialogsManager from \"../lib/appManagers/appDialogsManager\";\nimport appMessagesManager, {Dialog} from \"../lib/appManagers/appMessagesManager\";\nimport appPeersManager from \"../lib/appManagers/appPeersManager\";\nimport rootScope from \"../lib/rootScope\";\nimport { positionMenu, openBtnMenu } from \"./misc\";\nimport ButtonMenu, { ButtonMenuItemOptions } from \"./buttonMenu\";\nimport PopupDeleteDialog from \"./popups/deleteDialog\";\nimport { i18n } from \"../lib/langPack\";\nimport findUpTag from \"../helpers/dom/findUpTag\";\nimport appNotificationsManager from \"../lib/appManagers/appNotificationsManager\";\n\nexport default class DialogsContextMenu {\n private element: HTMLElement;\n private buttons: (ButtonMenuItemOptions & {verify: () => boolean})[];\n\n private selectedId: number;\n private filterId: number;\n private dialog: Dialog;\n\n private init() {\n this.buttons = [{\n icon: 'unread',\n text: 'MarkAsUnread',\n onClick: this.onUnreadClick,\n verify: () => {\n const isUnread = !!(this.dialog.pFlags?.unread_mark || this.dialog.unread_count);\n return !isUnread;\n }\n }, {\n icon: 'readchats',\n text: 'MarkAsRead',\n onClick: this.onUnreadClick,\n verify: () => { \n const isUnread = !!(this.dialog.pFlags?.unread_mark || this.dialog.unread_count);\n return isUnread;\n }\n }, {\n icon: 'pin',\n text: 'ChatList.Context.Pin',\n onClick: this.onPinClick,\n verify: () => {\n const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.filters[this.filterId].pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned;\n return !isPinned;\n }\n }, {\n icon: 'unpin',\n text: 'ChatList.Context.Unpin',\n onClick: this.onPinClick,\n verify: () => {\n const isPinned = this.filterId > 1 ? appMessagesManager.filtersStorage.filters[this.filterId].pinned_peers.includes(this.dialog.peerId) : !!this.dialog.pFlags?.pinned;\n return isPinned;\n }\n }, {\n icon: 'mute',\n text: 'ChatList.Context.Mute',\n onClick: this.onMuteClick,\n verify: () => {\n return this.selectedId !== rootScope.myId && !appNotificationsManager.isPeerLocalMuted(this.dialog.peerId); \n }\n }, {\n icon: 'unmute',\n text: 'ChatList.Context.Unmute',\n onClick: this.onUnmuteClick,\n verify: () => {\n return this.selectedId !== rootScope.myId && appNotificationsManager.isPeerLocalMuted(this.dialog.peerId); \n }\n }, {\n icon: 'archive',\n text: 'Archive',\n onClick: this.onArchiveClick,\n verify: () => this.filterId === 0 && this.selectedId !== rootScope.myId\n }, {\n icon: 'unarchive',\n text: 'Unarchive',\n onClick: this.onArchiveClick,\n verify: () => this.filterId === 1 && this.selectedId !== rootScope.myId\n }, {\n icon: 'delete danger',\n text: 'Delete',\n onClick: this.onDeleteClick,\n verify: () => true\n }];\n\n this.element = ButtonMenu(this.buttons);\n this.element.id = 'dialogs-contextmenu';\n this.element.classList.add('contextmenu');\n document.getElementById('page-chats').append(this.element);\n }\n\n private onArchiveClick = () => {\n let dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];\n if(dialog) {\n appMessagesManager.editPeerFolders([dialog.peerId], +!dialog.folder_id);\n }\n };\n\n private onPinClick = () => {\n appMessagesManager.toggleDialogPin(this.selectedId, this.filterId);\n };\n\n private onUnmuteClick = () => {\n appMessagesManager.mutePeer(this.selectedId, false);\n };\n \n private onMuteClick = () => {\n appMessagesManager.mutePeer(this.selectedId, true);\n };\n\n private onUnreadClick = () => {\n const dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];\n if(!dialog) return;\n\n if(dialog.unread_count) {\n appMessagesManager.readHistory(this.selectedId, dialog.top_message);\n appMessagesManager.markDialogUnread(this.selectedId, true);\n } else {\n appMessagesManager.markDialogUnread(this.selectedId);\n }\n };\n\n private onDeleteClick = () => {\n new PopupDeleteDialog(this.selectedId);\n };\n\n onContextMenu = (e: MouseEvent | Touch) => {\n if(this.init) {\n this.init();\n this.init = null;\n }\n\n let li: HTMLElement = null;\n \n try {\n li = findUpTag(e.target, 'LI');\n } catch(e) {}\n \n if(!li) return;\n\n if(e instanceof MouseEvent) e.preventDefault();\n if(this.element.classList.contains('active')) {\n return false;\n }\n if(e instanceof MouseEvent) e.cancelBubble = true;\n\n this.filterId = appDialogsManager.filterId;\n\n this.selectedId = +li.dataset.peerId;\n this.dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];\n\n this.buttons.forEach(button => {\n const good = button.verify();\n\n button.element.classList.toggle('hide', !good);\n });\n\n // delete button\n this.buttons[this.buttons.length - 1].element.lastChild.replaceWith(i18n(appPeersManager.getDeleteButtonText(this.selectedId)));\n\n li.classList.add('menu-open');\n positionMenu(e, this.element);\n openBtnMenu(this.element, () => {\n li.classList.remove('menu-open');\n this.selectedId = this.dialog = this.filterId = undefined;\n });\n };\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport AvatarElement from \"../../components/avatar\";\nimport DialogsContextMenu from \"../../components/dialogsContextMenu\";\nimport { horizontalMenu } from \"../../components/horizontalMenu\";\nimport { attachContextMenuListener, putPreloader } from \"../../components/misc\";\nimport { ripple } from \"../../components/ripple\";\n//import Scrollable from \"../../components/scrollable\";\nimport Scrollable, { ScrollableX, SliceSides } from \"../../components/scrollable\";\nimport { formatDateAccordingToTodayNew } from \"../../helpers/date\";\nimport { isSafari } from \"../../helpers/userAgent\";\nimport { logger, LogLevels } from \"../logger\";\nimport { RichTextProcessor } from \"../richtextprocessor\";\nimport rootScope from \"../rootScope\";\nimport { positionElementByIndex, replaceContent } from \"../../helpers/dom\";\nimport appImManager from \"./appImManager\";\nimport appMessagesManager, { Dialog } from \"./appMessagesManager\";\nimport {MyDialogFilter as DialogFilter} from \"../storages/filters\";\nimport appPeersManager from './appPeersManager';\nimport appStateManager from \"./appStateManager\";\nimport appUsersManager, { User } from \"./appUsersManager\";\nimport Button from \"../../components/button\";\nimport SetTransition from \"../../components/singleTransition\";\nimport sessionStorage from '../sessionStorage';\nimport apiUpdatesManager from \"./apiUpdatesManager\";\nimport appDraftsManager, { MyDraftMessage } from \"./appDraftsManager\";\nimport ProgressivePreloader from \"../../components/preloader\";\nimport App from \"../../config/app\";\nimport DEBUG, { MOUNT_CLASS_TO } from \"../../config/debug\";\nimport appNotificationsManager from \"./appNotificationsManager\";\nimport { InputNotifyPeer } from \"../../layer\";\nimport PeerTitle from \"../../components/peerTitle\";\nimport { i18n } from \"../langPack\";\nimport findUpTag from \"../../helpers/dom/findUpTag\";\nimport appChatsManager from \"./appChatsManager\";\n\nexport type DialogDom = {\n avatarEl: AvatarElement,\n captionDiv: HTMLDivElement,\n titleSpan: HTMLSpanElement,\n titleSpanContainer: HTMLSpanElement,\n statusSpan: HTMLSpanElement,\n lastTimeSpan: HTMLSpanElement,\n unreadMessagesSpan: HTMLSpanElement,\n lastMessageSpan: HTMLSpanElement,\n containerEl: HTMLElement,\n listEl: HTMLLIElement,\n muteAnimationTimeout?: number\n};\n\n//const testScroll = false;\n//let testTopSlice = 1;\n\nclass ConnectionStatusComponent {\n public static CHANGE_STATE_DELAY = 1000;\n\n private statusContainer: HTMLElement;\n private statusEl: HTMLElement;\n private statusPreloader: ProgressivePreloader;\n\n private currentText = '';\n\n private connecting = false;\n private updating = false;\n\n private log: ReturnType<typeof logger>;\n\n private setFirstConnectionTimeout: number;\n private setStateTimeout: number;\n\n constructor(chatsContainer: HTMLElement) {\n this.log = logger('CS');\n \n this.statusContainer = document.createElement('div');\n this.statusContainer.classList.add('connection-status');\n\n this.statusEl = Button('btn-primary bg-warning connection-status-button', {noRipple: true});\n this.statusPreloader = new ProgressivePreloader({cancelable: false});\n this.statusPreloader.constructContainer({color: 'transparent', bold: true});\n this.statusContainer.append(this.statusEl);\n\n chatsContainer.prepend(this.statusContainer);\n\n rootScope.on('connection_status_change', (e) => {\n const status = e;\n console.log(status);\n\n this.setConnectionStatus();\n });\n\n rootScope.on('state_synchronizing', (e) => {\n const channelId = e;\n if(!channelId) {\n this.updating = true;\n DEBUG && this.log('updating', this.updating);\n this.setState();\n }\n });\n\n rootScope.on('state_synchronized', (e) => {\n const channelId = e;\n DEBUG && this.log('state_synchronized', channelId);\n if(!channelId) {\n this.updating = false;\n DEBUG && this.log('updating', this.updating);\n this.setState();\n }\n });\n\n this.setFirstConnectionTimeout = window.setTimeout(this.setConnectionStatus, ConnectionStatusComponent.CHANGE_STATE_DELAY + 1e3);\n\n /* let bool = true;\n document.addEventListener('dblclick', () => {\n rootScope.broadcast('connection_status_change', {\n dcId: 2,\n isFileDownload: false,\n isFileNetworker: false,\n isFileUpload: false,\n name: \"NET-2\",\n online: bool = !bool,\n _: \"networkerStatus\"\n });\n }); */\n }\n\n private setConnectionStatus = () => {\n sessionStorage.get('dc').then(baseDcId => {\n if(!baseDcId) {\n baseDcId = App.baseDcId;\n }\n \n if(this.setFirstConnectionTimeout) {\n clearTimeout(this.setFirstConnectionTimeout);\n this.setFirstConnectionTimeout = 0;\n }\n\n const status = rootScope.connectionStatus['NET-' + baseDcId];\n const online = status && status.online;\n\n if(this.connecting && online) {\n apiUpdatesManager.forceGetDifference();\n }\n\n this.connecting = !online;\n DEBUG && this.log('connecting', this.connecting);\n this.setState();\n });\n };\n\n private setStatusText = (text: string) => {\n if(this.currentText === text) return;\n this.statusEl.innerText = this.currentText = text;\n this.statusPreloader.attach(this.statusEl);\n };\n\n private setState = () => {\n const timeout = ConnectionStatusComponent.CHANGE_STATE_DELAY;\n if(this.connecting) {\n this.setStatusText('Waiting for network...');\n } else if(this.updating) {\n this.setStatusText('Updating...');\n }\n\n DEBUG && this.log('setState', this.connecting || this.updating);\n window.requestAnimationFrame(() => {\n if(this.setStateTimeout) clearTimeout(this.setStateTimeout);\n\n const cb = () => {\n SetTransition(this.statusContainer, 'is-shown', this.connecting || this.updating, 200);\n this.setStateTimeout = 0;\n DEBUG && this.log('setState: isShown:', this.connecting || this.updating);\n };\n\n this.setStateTimeout = window.setTimeout(cb, timeout);\n //cb();\n /* if(timeout) this.setStateTimeout = window.setTimeout(cb, timeout);\n else cb(); */\n });\n };\n}\n\nexport class AppDialogsManager {\n public chatList: HTMLUListElement;\n\n public doms: {[peerId: number]: DialogDom} = {};\n\n public chatsContainer = document.getElementById('chatlist-container') as HTMLDivElement;\n private chatsPreloader: HTMLElement;\n\n public loadDialogsPromise: Promise<any>;\n\n public scroll: Scrollable = null;\n public _scroll: Scrollable = null;\n \n private log = logger('DIALOGS', LogLevels.log | LogLevels.error | LogLevels.warn | LogLevels.debug);\n\n public contextMenu = new DialogsContextMenu();\n\n public chatLists: {[filterId: number]: HTMLUListElement};\n public filterId: number;\n private folders: {[k in 'menu' | 'container' | 'menuScrollContainer']: HTMLElement} = {\n menu: document.getElementById('folders-tabs'),\n menuScrollContainer: null,\n container: document.getElementById('folders-container')\n };\n private filtersRendered: {\n [filterId: string]: {\n menu: HTMLElement, \n container: HTMLElement,\n unread: HTMLElement,\n title: HTMLElement\n }\n } = {};\n private showFiltersTimeout: number;\n private allUnreadCount: HTMLElement;\n\n private accumulateArchivedTimeout: number;\n\n //private topOffsetIndex = 0;\n\n private sliceTimeout: number;\n private reorderDialogsTimeout: number;\n\n private lastActiveElements: Set<HTMLElement> = new Set();\n\n constructor() {\n const archivedChatList = this.createChatList();\n this.chatLists = {\n 1: archivedChatList\n };\n\n this.setListClickListener(archivedChatList, null, true);\n //this.setListClickListener(archivedChatList, null, true); // * to test peer changing\n\n this.chatsPreloader = putPreloader(null, true);\n\n this.allUnreadCount = this.folders.menu.querySelector('.badge');\n \n this.folders.menuScrollContainer = this.folders.menu.parentElement;\n\n const bottomPart = document.createElement('div');\n bottomPart.classList.add('connection-status-bottom');\n bottomPart.append(this.folders.container);\n\n this.scroll = this._scroll = new Scrollable(bottomPart, 'CL', 500);\n this.scroll.container.addEventListener('scroll', this.onChatsRegularScroll);\n this.scroll.onScrolledTop = this.onChatsScrollTop;\n this.scroll.onScrolledBottom = this.onChatsScroll;\n //this.scroll.attachSentinels();\n\n /* if(isTouchSupported && isSafari) {\n let allowUp: boolean, allowDown: boolean, slideBeginY: number;\n const container = this.scroll.container;\n container.addEventListener('touchstart', (event) => {\n allowUp = container.scrollTop > 0;\n allowDown = (container.scrollTop < container.scrollHeight - container.clientHeight);\n // @ts-ignore\n slideBeginY = event.pageY;\n });\n \n container.addEventListener('touchmove', (event: any) => {\n var up = (event.pageY > slideBeginY);\n var down = (event.pageY < slideBeginY);\n slideBeginY = event.pageY;\n if((up && allowUp) || (down && allowDown)) {\n event.stopPropagation();\n } else if(up || down) {\n event.preventDefault();\n }\n });\n } */\n\n this.filterId = 0;\n this.addFilter({\n id: this.filterId,\n title: '',\n titleEl: i18n('ChatList.Filter.All'),\n orderIndex: 0\n });\n\n this.chatList = this.chatLists[this.filterId];\n this.scroll.setVirtualContainer(this.chatList);\n\n /* if(testScroll) {\n let i = 0;\n let add = () => {\n let li = document.createElement('li');\n li.dataset.id = '' + i;\n li.id = '' + i;\n li.innerHTML = `<div class=\"rp\"><avatar-element style=\"background-color: rgb(166, 149, 231); font-size: 0px;\"><img src=\"assets/img/pepe.jpg\"></avatar-element><div class=\"user-caption\"><p><span class=\"user-title\">${i}</span><span><span class=\"message-status\"></span><span class=\"message-time\">18:33</span></span></p><p><span class=\"user-last-message\"><b>-_-_-_-: </b>qweasd</span><span></span></p></div></div>`;\n i++;\n this.scroll.append(li);\n };\n for(let i = 0; i < 500; ++i) {\n add();\n }\n (window as any).addElement = add;\n } */\n\n rootScope.on('user_update', (e) => {\n const userId = e;\n const user = appUsersManager.getUser(userId);\n const dialog = appMessagesManager.getDialogByPeerId(user.id)[0];\n //console.log('updating user:', user, dialog);\n\n if(dialog && !appUsersManager.isBot(dialog.peerId) && dialog.peerId !== rootScope.myId) {\n const online = user.status?._ === 'userStatusOnline';\n const dom = this.getDialogDom(dialog.peerId);\n\n if(dom) {\n dom.avatarEl.classList.toggle('is-online', online);\n }\n }\n });\n\n /* rootScope.$on('dialog_top', (e) => {\n const dialog = e;\n\n this.setLastMessage(dialog);\n this.setDialogPosition(dialog);\n\n this.setFiltersUnreadCount();\n }); */\n\n rootScope.on('dialog_flush', (e) => {\n const peerId: number = e.peerId;\n const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];\n if(dialog) {\n this.setLastMessage(dialog);\n this.validateForFilter();\n this.setFiltersUnreadCount();\n }\n });\n\n rootScope.on('dialogs_multiupdate', (e) => {\n const dialogs = e;\n\n for(const id in dialogs) {\n const dialog = dialogs[id];\n this.updateDialog(dialog);\n }\n\n this.validateForFilter();\n this.setFiltersUnreadCount();\n });\n\n rootScope.on('dialog_drop', (e) => {\n const {peerId, dialog} = e;\n\n const dom = this.getDialogDom(peerId);\n if(dom) {\n dom.listEl.remove();\n delete this.doms[peerId];\n }\n\n this.setFiltersUnreadCount();\n });\n\n rootScope.on('dialog_unread', (e) => {\n const info = e;\n\n const dialog = appMessagesManager.getDialogByPeerId(info.peerId)[0];\n if(dialog) {\n this.setUnreadMessages(dialog);\n this.validateForFilter();\n this.setFiltersUnreadCount();\n }\n });\n\n rootScope.on('dialog_notify_settings', (dialog) => {\n this.setUnreadMessages(dialog); // возможно это не нужно, но нужно менять is-muted\n });\n\n rootScope.on('dialog_draft', (e) => {\n const dialog = appMessagesManager.getDialogByPeerId(e.peerId)[0];\n if(dialog) {\n this.updateDialog(dialog);\n }\n });\n\n rootScope.on('peer_changed', (e) => {\n const peerId = e;\n\n //const perf = performance.now();\n for(const element of this.lastActiveElements) {\n if(+element.dataset.peerId !== peerId) {\n element.classList.remove('active');\n this.lastActiveElements.delete(element);\n }\n }\n\n const elements = Array.from(document.querySelectorAll(`[data-autonomous=\"0\"] li[data-peer-id=\"${peerId}\"]`)) as HTMLElement[];\n elements.forEach(element => {\n element.classList.add('active');\n this.lastActiveElements.add(element);\n });\n //this.log('peer_changed total time:', performance.now() - perf);\n });\n\n rootScope.on('filter_update', (e) => {\n const filter: DialogFilter = e;\n if(!this.filtersRendered[filter.id]) {\n this.addFilter(filter);\n return;\n } else if(filter.id === this.filterId) { // это нет тут смысла вызывать, так как будет dialogs_multiupdate\n //this.validateForFilter();\n const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);\n this.validateForFilter();\n for(let i = 0, length = folder.length; i < length; ++i) {\n const dialog = folder[i];\n this.updateDialog(dialog);\n }\n this.setFiltersUnreadCount();\n }\n\n const elements = this.filtersRendered[filter.id];\n elements.title.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);\n });\n\n rootScope.on('filter_delete', (e) => {\n const filter: DialogFilter = e;\n const elements = this.filtersRendered[filter.id];\n if(!elements) return;\n\n // set tab\n //(this.folders.menu.firstElementChild.children[Math.max(0, filter.id - 2)] as HTMLElement).click();\n (this.folders.menu.firstElementChild as HTMLElement).click();\n\n elements.container.remove();\n elements.menu.remove();\n \n delete this.chatLists[filter.id];\n delete this.filtersRendered[filter.id];\n\n if(Object.keys(this.filtersRendered).length <= 1) {\n this.folders.menuScrollContainer.classList.add('hide');\n }\n });\n\n rootScope.on('filter_order', (e) => {\n const order = e;\n \n const containerToAppend = this.folders.menu as HTMLElement;\n order.forEach((filterId) => {\n const filter = appMessagesManager.filtersStorage.filters[filterId];\n const renderedFilter = this.filtersRendered[filterId];\n\n positionElementByIndex(renderedFilter.menu, containerToAppend, filter.orderIndex);\n positionElementByIndex(renderedFilter.container, this.folders.container, filter.orderIndex);\n });\n\n /* if(this.filterId) {\n const tabIndex = order.indexOf(this.filterId) + 1;\n selectTab.prevId = tabIndex;\n } */\n });\n\n rootScope.on('peer_typings', (e) => {\n const {peerId, typings} = e;\n\n const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];\n if(!dialog) return;\n\n if(typings.length) {\n this.setTyping(dialog);\n } else {\n this.unsetTyping(dialog);\n }\n });\n\n const foldersScrollable = new ScrollableX(this.folders.menuScrollContainer);\n bottomPart.prepend(this.folders.menuScrollContainer);\n const selectTab = horizontalMenu(this.folders.menu, this.folders.container, (id, tabContent) => {\n /* if(id !== 0) {\n id += 1;\n } */\n\n id = +tabContent.dataset.filterId || 0;\n\n if(this.filterId === id) return;\n\n this.chatLists[id].innerHTML = '';\n this.scroll.setVirtualContainer(this.chatLists[id]);\n this.filterId = id;\n this.onTabChange();\n }, () => {\n for(const folderId in this.chatLists) {\n if(+folderId !== this.filterId) {\n this.chatLists[folderId].innerHTML = '';\n }\n }\n }, undefined, foldersScrollable);\n\n //selectTab(0);\n (this.folders.menu.firstElementChild as HTMLElement).click();\n appStateManager.getState().then((state) => {\n appNotificationsManager.getNotifyPeerTypeSettings();\n \n const getFiltersPromise = appMessagesManager.filtersStorage.getDialogFilters();\n getFiltersPromise.then((filters) => {\n for(const filter of filters) {\n this.addFilter(filter);\n }\n });\n\n if(state.dialogs?.length) {\n appDraftsManager.getAllDrafts();\n appDraftsManager.addMissedDialogs();\n }\n\n return this.loadDialogs();\n }).then(() => {\n const allDialogsLoaded = appMessagesManager.dialogsStorage.allDialogsLoaded;\n const wasLoaded = allDialogsLoaded[0] || allDialogsLoaded[1];\n const a: Promise<any> = allDialogsLoaded[0] ? Promise.resolve() : appMessagesManager.getConversationsAll('', 0);\n const b: Promise<any> = allDialogsLoaded[1] ? Promise.resolve() : appMessagesManager.getConversationsAll('', 1);\n a.finally(() => {\n b.then(() => {\n this.accumulateArchivedUnread();\n\n if(wasLoaded) {\n (apiUpdatesManager.updatesState.syncLoading || Promise.resolve()).then(() => {\n appMessagesManager.refreshConversations();\n });\n }\n });\n });\n });\n\n new ConnectionStatusComponent(this.chatsContainer);\n this.chatsContainer.append(bottomPart);\n }\n\n private getOffset(side: 'top' | 'bottom'): {index: number, pos: number} {\n if(!this.scroll.loadedAll[side]) {\n const element = (side === 'top' ? this.chatList.firstElementChild : this.chatList.lastElementChild) as HTMLElement;\n if(element) {\n const peerId = +element.dataset.peerId;\n const dialog = appMessagesManager.getDialogByPeerId(peerId);\n return {index: dialog[0].index, pos: dialog[1]};\n }\n }\n\n return {index: 0, pos: -1};\n }\n\n private isDialogMustBeInViewport(dialog: Dialog) {\n //return true;\n const topOffset = this.getOffset('top');\n const bottomOffset = this.getOffset('bottom');\n \n if(!topOffset.index && !bottomOffset.index) {\n return true;\n }\n \n const index = dialog.index;\n return (!topOffset.index || index <= topOffset.index) && (!bottomOffset.index || index >= bottomOffset.index);\n }\n\n private updateDialog(dialog: Dialog) {\n if(!dialog) {\n return;\n }\n\n if(this.isDialogMustBeInViewport(dialog)) {\n if(!this.doms.hasOwnProperty(dialog.peerId)) {\n const ret = this.addDialogNew({dialog});\n if(ret) {\n const idx = appMessagesManager.getDialogByPeerId(dialog.peerId)[1];\n positionElementByIndex(ret.dom.listEl, this.chatList, idx);\n } else {\n return;\n }\n }\n } else {\n const dom = this.getDialogDom(dialog.peerId);\n if(dom) {\n dom.listEl.remove();\n delete this.doms[dialog.peerId];\n }\n\n return;\n }\n\n /* const topOffset = this.getOffset('top');\n if(topOffset.index && dialog.index > topOffset.index) {\n const dom = this.getDialogDom(dialog.peerId);\n if(dom) {\n dom.listEl.remove();\n delete this.doms[dialog.peerId];\n }\n\n return;\n }\n\n if(!this.doms.hasOwnProperty(dialog.peerId)) {\n this.addDialogNew({dialog});\n } */\n\n if(this.getDialogDom(dialog.peerId)) {\n this.setLastMessage(dialog);\n this.reorderDialogs();\n }\n }\n\n onTabChange = () => {\n this.doms = {};\n this.scroll.loadedAll.top = true;\n this.scroll.loadedAll.bottom = false;\n this.loadDialogsPromise = undefined;\n this.chatList = this.chatLists[this.filterId];\n this.loadDialogs();\n };\n\n private setFilterUnreadCount(filterId: number, folder?: Dialog[]) {\n const unreadSpan = filterId === 0 ? this.allUnreadCount : this.filtersRendered[filterId]?.unread;\n if(!unreadSpan) {\n return;\n }\n\n folder = folder || appMessagesManager.dialogsStorage.getFolder(filterId);\n let mutedCount = 0;\n let notMutedCount = 0;\n folder.forEach(dialog => {\n const isMuted = appNotificationsManager.isPeerLocalMuted(dialog.peerId, true);\n\n if(isMuted && filterId === 0) {\n return;\n }\n\n const value = +!!dialog.unread_count || +dialog.pFlags.unread_mark || 0; // * unread_mark can be undefined\n if(isMuted) mutedCount += value;\n else notMutedCount += value;\n });\n \n unreadSpan.classList.toggle('badge-gray', mutedCount && !notMutedCount);\n \n const sum = mutedCount + notMutedCount;\n unreadSpan.innerText = sum ? '' + sum : '';\n }\n\n private setFiltersUnreadCount() {\n for(const filterId in this.filtersRendered) {\n this.setFilterUnreadCount(+filterId);\n }\n\n this.setFilterUnreadCount(0);\n }\n\n /**\n * Удалит неподходящие чаты из списка, но не добавит их(!)\n */\n private validateForFilter() {\n // !WARNING, возможно это было зачем-то, но комментарий исправил архивирование\n //if(this.filterId === 0) return;\n\n const folder = appMessagesManager.dialogsStorage.getFolder(this.filterId);\n for(const _peerId in this.doms) {\n const peerId = +_peerId;\n\n // если больше не подходит по фильтру, удаляем\n if(folder.findIndex((dialog) => dialog.peerId === peerId) === -1) {\n const listEl = this.doms[peerId].listEl;\n listEl.remove();\n delete this.doms[peerId];\n }\n }\n }\n\n private addFilter(filter: Pick<DialogFilter, 'title' | 'id' | 'orderIndex'> & Partial<{titleEl: HTMLElement}>) {\n if(this.filtersRendered[filter.id]) return;\n\n const menuTab = document.createElement('div');\n menuTab.classList.add('menu-horizontal-div-item');\n const span = document.createElement('span');\n const titleSpan = document.createElement('span');\n titleSpan.classList.add('text-super');\n if(filter.titleEl) titleSpan.append(filter.titleEl);\n else titleSpan.innerHTML = RichTextProcessor.wrapEmojiText(filter.title);\n const unreadSpan = document.createElement('div');\n unreadSpan.classList.add('badge', 'badge-20', 'badge-primary');\n const i = document.createElement('i');\n span.append(titleSpan, unreadSpan, i);\n menuTab.append(span);\n ripple(menuTab);\n\n const containerToAppend = this.folders.menu as HTMLElement;\n positionElementByIndex(menuTab, containerToAppend, filter.orderIndex);\n //containerToAppend.append(li);\n\n const ul = this.createChatList();\n const div = document.createElement('div');\n div.append(ul);\n div.dataset.filterId = '' + filter.id;\n //this.folders.container.append(div);\n positionElementByIndex(div, this.folders.container, filter.orderIndex);\n\n this.chatLists[filter.id] = ul;\n this.setListClickListener(ul, null, true);\n\n this.filtersRendered[filter.id] = {\n menu: menuTab,\n container: div,\n unread: unreadSpan,\n title: titleSpan\n };\n\n if(!this.showFiltersTimeout && Object.keys(this.filtersRendered).length > 1) {\n this.showFiltersTimeout = window.setTimeout(() => {\n this.showFiltersTimeout = 0;\n this.folders.menuScrollContainer.classList.remove('hide');\n this.setFiltersUnreadCount();\n }, 0);\n }\n }\n\n private loadDialogs(side: SliceSides = 'bottom') {\n /* if(testScroll) {\n return;\n } */\n \n if(this.loadDialogsPromise/* || 1 === 1 */) return this.loadDialogsPromise;\n\n const promise = new Promise<void>(async(resolve, reject) => {\n if(!this.chatList.childElementCount) {\n const container = this.chatList.parentElement;\n container.append(this.chatsPreloader);\n }\n \n //return;\n \n const filterId = this.filterId;\n let loadCount = 30/*this.chatsLoadCount */;\n \n const storage = appMessagesManager.dialogsStorage.getFolder(filterId);\n let offsetIndex = 0;\n \n if(side === 'top') {\n const element = this.chatList.firstElementChild as HTMLElement;\n if(element) {\n const peerId = +element.dataset.peerId;\n const index = storage.findIndex(dialog => dialog.peerId === peerId);\n const needIndex = Math.max(0, index - loadCount);\n loadCount = index - needIndex;\n offsetIndex = storage[needIndex].index + 1;\n }\n } else {\n const element = this.chatList.lastElementChild as HTMLElement;\n if(element) {\n const peerId = +element.dataset.peerId;\n const dialog = storage.find(dialog => dialog.peerId === peerId);\n offsetIndex = dialog.index;\n }\n }\n \n //let offset = storage[storage.length - 1]?.index || 0;\n \n try {\n //console.time('getDialogs time');\n \n const getConversationPromise = (this.filterId > 1 ? appUsersManager.getContacts() as Promise<any> : Promise.resolve()).then(() => {\n return appMessagesManager.getConversations('', offsetIndex, loadCount, filterId);\n });\n \n const result = await getConversationPromise;\n \n if(this.filterId !== filterId) {\n return;\n }\n \n //console.timeEnd('getDialogs time');\n \n // * loaded all\n //if(!result.dialogs.length || this.chatList.childElementCount === result.count) {\n // !result.dialogs.length не подходит, так как при супердревном диалоге getConversations его не выдаст.\n //if(this.chatList.childElementCount === result.count) {\n if(side === 'bottom') {\n if(result.isEnd) {\n this.scroll.loadedAll[side] = true;\n }\n } else {\n const storage = appMessagesManager.dialogsStorage.getFolder(filterId);\n if(!result.dialogs.length || (storage.length && storage[0].index < offsetIndex)) {\n this.scroll.loadedAll[side] = true;\n }\n }\n \n if(result.dialogs.length) {\n const dialogs = side === 'top' ? result.dialogs.slice().reverse() : result.dialogs;\n \n dialogs.forEach((dialog) => {\n this.addDialogNew({\n dialog,\n append: side === 'bottom'\n });\n });\n }\n \n this.log.debug('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.chatList.childElementCount);\n \n setTimeout(() => {\n this.scroll.onScroll();\n }, 0);\n } catch(err) {\n this.log.error(err);\n }\n \n this.chatsPreloader.remove();\n resolve();\n });\n\n return this.loadDialogsPromise = promise.finally(() => {\n this.loadDialogsPromise = undefined;\n });\n }\n\n public onChatsRegularScroll = () => {\n if(this.sliceTimeout) clearTimeout(this.sliceTimeout);\n this.sliceTimeout = window.setTimeout(() => {\n this.sliceTimeout = undefined;\n\n if(!this.chatList.childElementCount) {\n return;\n }\n\n /* const observer = new IntersectionObserver((entries) => {\n const \n });\n\n Array.from(this.chatList.children).forEach(el => {\n observer.observe(el);\n }); */\n\n //const scrollTopWas = this.scroll.scrollTop;\n\n const firstElementChild = this.chatList.firstElementChild;\n const rectContainer = this.scroll.container.getBoundingClientRect();\n const rectTarget = firstElementChild.getBoundingClientRect();\n const children = Array.from(this.scroll.splitUp.children) as HTMLElement[];\n\n const offsetTop = this.folders.container.offsetTop;\n const firstY = rectContainer.y + offsetTop;\n const lastY = rectContainer.y;\n \n const firstElement = findUpTag(document.elementFromPoint(Math.ceil(rectTarget.x), Math.ceil(firstY + 1)), firstElementChild.tagName) as HTMLElement;\n const lastElement = findUpTag(document.elementFromPoint(Math.ceil(rectTarget.x), Math.floor(lastY + rectContainer.height - 1)), firstElementChild.tagName) as HTMLElement;\n\n //alert('got element:' + rect.y);\n\n if(!firstElement || !lastElement) {\n return;\n }\n\n //alert('got element:' + !!firstElement);\n\n const firstElementRect = firstElement.getBoundingClientRect();\n const elementOverflow = firstElementRect.y - firstY;\n\n const sliced: HTMLElement[] = [];\n const firstIndex = children.indexOf(firstElement);\n const lastIndex = children.indexOf(lastElement);\n\n const saveLength = 10;\n\n const sliceFromStart = isSafari ? [] : children.slice(0, Math.max(0, firstIndex - saveLength));\n const sliceFromEnd = children.slice(lastIndex + saveLength);\n\n /* if(sliceFromStart.length !== sliceFromEnd.length) {\n console.log('not equal', sliceFromStart.length, sliceFromEnd.length);\n }\n\n if(sliceFromStart.length > sliceFromEnd.length) {\n const diff = sliceFromStart.length - sliceFromEnd.length;\n sliceFromStart.splice(0, diff);\n } else if(sliceFromEnd.length > sliceFromStart.length) {\n const diff = sliceFromEnd.length - sliceFromStart.length;\n sliceFromEnd.splice(sliceFromEnd.length - diff, diff);\n } */\n\n if(sliceFromStart.length) {\n this.scroll.loadedAll['top'] = false;\n }\n\n if(sliceFromEnd.length) {\n this.scroll.loadedAll['bottom'] = false;\n }\n\n sliced.push(...sliceFromStart);\n sliced.push(...sliceFromEnd);\n\n sliced.forEach(el => {\n el.remove();\n const peerId = +el.dataset.peerId;\n delete this.doms[peerId];\n });\n\n //this.log('[slicer] elements', firstElement, lastElement, rect, sliced, sliceFromStart.length, sliceFromEnd.length);\n\n //this.log('[slicer] reset scrollTop', this.scroll.scrollTop, firstElement.offsetTop, firstElementRect.y, rect.y, elementOverflow);\n\n //alert('left length:' + children.length);\n\n this.scroll.scrollTop = firstElement.offsetTop - elementOverflow;\n /* const firstElementRect = firstElement.getBoundingClientRect();\n const scrollTop = */\n\n //this.scroll.scrollIntoView(firstElement, false);\n }, 200);\n };\n\n public onChatsScrollTop = () => {\n this.onChatsScroll('top');\n };\n \n public onChatsScroll = (side: SliceSides = 'bottom') => {\n if(this.scroll.loadedAll[side] || this.loadDialogsPromise) return;\n this.log('onChatsScroll', side);\n this.loadDialogs(side);\n };\n\n public setListClickListener(list: HTMLUListElement, onFound?: () => void, withContext = false, autonomous = false, openInner = false) {\n let lastActiveListElement: HTMLElement;\n\n const setPeerFunc = (openInner ? appImManager.setInnerPeer : appImManager.setPeer).bind(appImManager);\n\n list.dataset.autonomous = '' + +autonomous;\n list.addEventListener('mousedown', (e) => {\n if(e.button !== 0) return;\n //cancelEvent(e);\n\n this.log('dialogs click list');\n const target = e.target as HTMLElement;\n const elem = findUpTag(target, 'LI');\n\n if(!elem) {\n return;\n }\n\n if(autonomous) {\n const sameElement = lastActiveListElement === elem;\n if(lastActiveListElement && !sameElement) {\n lastActiveListElement.classList.remove('active');\n }\n\n if(elem) {\n elem.classList.add('active');\n lastActiveListElement = elem;\n this.lastActiveElements.add(elem);\n }\n }\n\n if(elem) {\n if(onFound) onFound();\n\n const peerId = +elem.dataset.peerId;\n const lastMsgId = +elem.dataset.mid || undefined;\n\n setPeerFunc(peerId, lastMsgId);\n } else {\n setPeerFunc(0);\n }\n }, {capture: true});\n\n if(DEBUG) {\n list.addEventListener('dblclick', (e) => {\n const li = findUpTag(e.target, 'LI');\n if(li) {\n const peerId = +li.dataset.peerId;\n this.log('debug dialog:', appMessagesManager.getDialogByPeerId(peerId));\n }\n });\n }\n\n if(withContext) {\n attachContextMenuListener(list, this.contextMenu.onContextMenu);\n }\n }\n\n public createChatList(/* options: {\n avatarSize?: number,\n handheldsSize?: number,\n //size?: number,\n } = {} */) {\n const list = document.createElement('ul');\n list.classList.add('chatlist'/* , \n 'chatlist-avatar-' + (options.avatarSize || 54) *//* , 'chatlist-' + (options.size || 72) */);\n\n /* if(options.handheldsSize) {\n list.classList.add('chatlist-handhelds-' + options.handheldsSize);\n } */\n\n return list;\n }\n\n private reorderDialogs() {\n //const perf = performance.now();\n if(this.reorderDialogsTimeout) {\n window.cancelAnimationFrame(this.reorderDialogsTimeout);\n }\n \n this.reorderDialogsTimeout = window.requestAnimationFrame(() => {\n this.reorderDialogsTimeout = 0;\n const offset = Math.max(0, this.getOffset('top').pos);\n \n const dialogs = appMessagesManager.dialogsStorage.getFolder(this.filterId);\n const currentOrder = (Array.from(this.chatList.children) as HTMLElement[]).map(el => +el.dataset.peerId);\n \n dialogs.forEach((dialog, index) => {\n const dom = this.getDialogDom(dialog.peerId);\n if(!dom) {\n return;\n }\n \n const needIndex = index - offset;\n if(needIndex > currentOrder.length) {\n dom.listEl.remove();\n delete this.doms[dialog.peerId];\n return;\n }\n\n const peerIdByIndex = currentOrder[needIndex];\n \n if(peerIdByIndex !== dialog.peerId) {\n if(positionElementByIndex(dom.listEl, this.chatList, needIndex)) {\n this.log.debug('setDialogPosition:', dialog, dom, peerIdByIndex, needIndex);\n }\n }\n });\n \n //this.log('Reorder time:', performance.now() - perf);\n });\n }\n\n public setLastMessage(dialog: Dialog, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {\n ///////console.log('setlastMessage:', lastMessage);\n if(!dom) {\n dom = this.getDialogDom(dialog.peerId);\n\n if(!dom) {\n //this.log.error('no dom for dialog:', dialog, lastMessage, dom, highlightWord);\n return;\n }\n }\n\n let draftMessage: MyDraftMessage;\n if(!lastMessage) {\n if(dialog.draft && dialog.draft._ === 'draftMessage') {\n draftMessage = dialog.draft;\n }\n \n lastMessage = appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);\n }\n\n if(lastMessage._ === 'messageEmpty'/* || (lastMessage._ === 'messageService' && !lastMessage.rReply) */) {\n dom.lastMessageSpan.innerHTML = '';\n dom.lastTimeSpan.innerHTML = '';\n delete dom.listEl.dataset.mid;\n return;\n }\n\n let peer = dialog.peer;\n let peerId = dialog.peerId;\n //let peerId = appMessagesManager.getMessagePeer(lastMessage);\n\n //console.log('setting last message:', lastMessage);\n\n /* if(!dom.lastMessageSpan.classList.contains('user-typing')) */ {\n\n dom.lastMessageSpan.textContent = '';\n if(highlightWord && lastMessage.message) {\n dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(lastMessage, undefined, undefined, false, highlightWord));\n } else if(draftMessage) {\n dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(draftMessage));\n } else if(!lastMessage.deleted) {\n dom.lastMessageSpan.append(appMessagesManager.wrapMessageForReply(lastMessage));\n }\n \n /* if(lastMessage.from_id === auth.id) { // You: */\n if(draftMessage) {\n const bold = document.createElement('b');\n bold.classList.add('danger');\n bold.append(i18n('Draft'));\n bold.append(': ');\n dom.lastMessageSpan.prepend(bold);\n } else if(peer._ !== 'peerUser' && peerId !== lastMessage.fromId && !lastMessage.action) {\n const sender = appPeersManager.getPeer(lastMessage.fromId);\n if(sender && sender.id) {\n const senderBold = document.createElement('b');\n\n if(sender.id === rootScope.myId) {\n senderBold.append(i18n('FromYou'));\n } else {\n //str = sender.first_name || sender.last_name || sender.username;\n senderBold.append(new PeerTitle({\n peerId: lastMessage.fromId,\n onlyFirstName: true,\n }).element);\n }\n\n senderBold.append(': ');\n //console.log(sender, senderBold.innerText);\n dom.lastMessageSpan.prepend(senderBold);\n } //////// else console.log('no sender', lastMessage, peerId);\n }\n }\n\n if(!lastMessage.deleted || draftMessage/* && lastMessage._ !== 'draftMessage' */) {\n const date = draftMessage ? Math.max(draftMessage.date, lastMessage.date || 0) : lastMessage.date;\n dom.lastTimeSpan.textContent = '';\n dom.lastTimeSpan.append(formatDateAccordingToTodayNew(new Date(date * 1000)));\n } else dom.lastTimeSpan.textContent = '';\n\n if(this.doms[peerId] === dom) {\n this.setUnreadMessages(dialog);\n } else { // means search\n dom.listEl.dataset.mid = lastMessage.mid;\n }\n }\n\n private setUnreadMessages(dialog: Dialog) {\n const dom = this.getDialogDom(dialog.peerId);\n\n if(dialog.folder_id === 1) {\n this.accumulateArchivedUnread();\n }\n\n if(!dom) {\n //this.log.error('setUnreadMessages no dom!', dialog);\n return;\n }\n\n const isMuted = appNotificationsManager.isPeerLocalMuted(dialog.peerId, true);\n const wasMuted = dom.listEl.classList.contains('is-muted');\n if(isMuted !== wasMuted) {\n SetTransition(dom.listEl, 'is-muted', isMuted, 200);\n }\n\n const lastMessage = dialog.draft && dialog.draft._ === 'draftMessage' ? \n dialog.draft : \n appMessagesManager.getMessageByPeer(dialog.peerId, dialog.top_message);\n if(lastMessage._ !== 'messageEmpty' && !lastMessage.deleted && \n lastMessage.pFlags.out && lastMessage.peerId !== rootScope.myId/* && \n dialog.read_outbox_max_id */) { // maybe comment, 06.20.2020\n const outgoing = (lastMessage.pFlags && lastMessage.pFlags.unread)\n /* && dialog.read_outbox_max_id !== 0 */; // maybe uncomment, 31.01.2020\n \n //console.log('outgoing', outgoing, lastMessage);\n \n if(outgoing) {\n dom.statusSpan.classList.remove('tgico-checks');\n dom.statusSpan.classList.add('tgico-check');\n } else {\n dom.statusSpan.classList.remove('tgico-check');\n dom.statusSpan.classList.add('tgico-checks');\n }\n } else dom.statusSpan.classList.remove('tgico-check', 'tgico-checks');\n\n dom.unreadMessagesSpan.innerText = '';\n\n const filter = appMessagesManager.filtersStorage.filters[this.filterId];\n let isPinned: boolean;\n if(filter) {\n isPinned = filter.pinned_peers.findIndex(peerId => peerId === dialog.peerId) !== -1;\n } else {\n isPinned = !!dialog.pFlags.pinned;\n }\n\n if(isPinned) {\n dom.unreadMessagesSpan.classList.add('tgico-chatspinned', 'tgico');\n } else {\n dom.unreadMessagesSpan.classList.remove('tgico-chatspinned', 'tgico');\n }\n\n if(dialog.unread_count || dialog.pFlags.unread_mark) {\n //dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count ? formatNumber(dialog.unread_count, 1) : ' ');\n dom.unreadMessagesSpan.innerText = '' + (dialog.unread_count || ' ');\n dom.unreadMessagesSpan.classList.add('unread');\n } else {\n dom.unreadMessagesSpan.classList.remove('unread');\n }\n }\n\n private accumulateArchivedUnread() {\n if(this.accumulateArchivedTimeout) return;\n this.accumulateArchivedTimeout = window.setTimeout(() => {\n this.accumulateArchivedTimeout = 0;\n const dialogs = appMessagesManager.dialogsStorage.getFolder(1);\n const sum = dialogs.reduce((acc, dialog) => acc + dialog.unread_count, 0);\n rootScope.broadcast('dialogs_archived_unread', {count: sum});\n }, 0);\n }\n\n private getDialogDom(peerId: number) {\n return this.doms[peerId];\n }\n\n public addDialogNew(options: {\n dialog: Dialog | number,\n container?: HTMLUListElement | Scrollable | false,\n drawStatus?: boolean,\n rippleEnabled?: boolean,\n onlyFirstName?: boolean,\n meAsSaved?: boolean,\n append?: boolean,\n avatarSize?: number,\n autonomous?: boolean\n }) {\n return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous);\n }\n\n public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable | false, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true, avatarSize = 54, autonomous = !!container) {\n let dialog: Dialog;\n \n if(typeof(_dialog) === 'number') {\n let originalDialog = appMessagesManager.getDialogByPeerId(_dialog)[0];\n if(!originalDialog) {\n originalDialog = {\n peerId: _dialog,\n peer: appPeersManager.getOutputPeer(_dialog),\n pFlags: {}\n } as any;\n }\n\n dialog = originalDialog;\n } else {\n dialog = _dialog;\n }\n\n const peerId: number = dialog.peerId;\n\n if(container === undefined) {\n if(this.doms[peerId]) return;\n\n const filter = appMessagesManager.filtersStorage.filters[this.filterId];\n if((filter && !appMessagesManager.filtersStorage.testDialogForFilter(dialog, filter)) || (!filter && this.filterId !== dialog.folder_id)) {\n return;\n }\n }\n\n const avatarEl = new AvatarElement();\n avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');\n avatarEl.setAttribute('peer', '' + peerId);\n avatarEl.classList.add('dialog-avatar', 'avatar-' + avatarSize);\n\n if(drawStatus && peerId !== rootScope.myId && dialog.peer) {\n const peer = dialog.peer;\n \n switch(peer._) {\n case 'peerUser':\n const user = appUsersManager.getUser(peerId);\n //console.log('found user', user);\n \n if(user.status && user.status._ === 'userStatusOnline') {\n avatarEl.classList.add('is-online');\n }\n \n break;\n default:\n break;\n }\n }\n\n const captionDiv = document.createElement('div');\n captionDiv.classList.add('user-caption');\n\n const titleSpanContainer = document.createElement('span');\n titleSpanContainer.classList.add('user-title');\n\n const peerTitle = new PeerTitle({\n peerId,\n dialog: meAsSaved,\n onlyFirstName,\n plainText: false\n });\n\n titleSpanContainer.append(peerTitle.element);\n //p.classList.add('')\n\n // в других случаях иконка верификации не нужна (а первый - это главные чатлисты)\n //if(!container) {\n const peer = appPeersManager.getPeer(peerId);\n\n // for muted icon\n titleSpanContainer.classList.add('tgico'); // * эта строка будет актуальна только для !container, но ладно\n\n if(peer?.pFlags?.verified) {\n titleSpanContainer.classList.add('is-verified');\n titleSpanContainer.append(generateVerifiedIcon());\n }\n //}\n \n const span = document.createElement('span');\n span.classList.add('user-last-message');\n\n //captionDiv.append(titleSpan);\n //captionDiv.append(span);\n\n const li = document.createElement('li');\n if(rippleEnabled) {\n ripple(li);\n }\n\n li.append(avatarEl, captionDiv);\n li.dataset.peerId = '' + peerId;\n\n const statusSpan = document.createElement('span');\n statusSpan.classList.add('message-status');\n\n const lastTimeSpan = document.createElement('span');\n lastTimeSpan.classList.add('message-time');\n\n const unreadMessagesSpan = document.createElement('div');\n unreadMessagesSpan.className = 'dialog-subtitle-badge badge badge-24';\n\n const titleP = document.createElement('p');\n titleP.classList.add('dialog-title');\n\n const rightSpan = document.createElement('span');\n rightSpan.classList.add('dialog-title-details');\n rightSpan.append(statusSpan, lastTimeSpan);\n titleP.append(titleSpanContainer, rightSpan);\n\n const messageP = document.createElement('p');\n messageP.classList.add('dialog-subtitle');\n messageP.append(span, unreadMessagesSpan);\n\n captionDiv.append(titleP, messageP);\n\n const dom: DialogDom = {\n avatarEl,\n captionDiv,\n titleSpan: peerTitle.element,\n titleSpanContainer,\n statusSpan,\n lastTimeSpan,\n unreadMessagesSpan,\n lastMessageSpan: span,\n containerEl: li,\n listEl: li\n };\n\n /* let good = false;\n for(const folderId in this.chatLists) {\n if(this.chatLists[folderId] === container) {\n good = true;\n }\n } */\n const method: 'append' | 'prepend' = append ? 'append' : 'prepend';\n if(container === undefined/* || good */) {\n this.scroll[method](li);\n\n this.doms[dialog.peerId] = dom;\n\n /* if(container) {\n container.append(li);\n } */\n\n const isMuted = appNotificationsManager.isPeerLocalMuted(dialog.peerId, true);\n if(isMuted) {\n li.classList.add('is-muted');\n }\n\n this.setLastMessage(dialog);\n } else if(container) {\n container[method](li);\n }\n\n if(!autonomous && appImManager.chat?.peerId === peerId) {\n li.classList.add('active');\n this.lastActiveElements.add(li);\n } \n \n return {dom, dialog};\n }\n\n public setTyping(dialog: Dialog) {\n const dom = this.getDialogDom(dialog.peerId);\n if(!dom) {\n return;\n }\n\n let typingElement = dom.lastMessageSpan.querySelector('.peer-typing-container') as HTMLElement;\n if(typingElement) {\n appImManager.getPeerTyping(dialog.peerId, typingElement);\n } else {\n typingElement = appImManager.getPeerTyping(dialog.peerId);\n replaceContent(dom.lastMessageSpan, typingElement);\n dom.lastMessageSpan.classList.add('user-typing');\n }\n }\n\n public unsetTyping(dialog: Dialog) {\n const dom = this.getDialogDom(dialog.peerId);\n if(!dom) {\n return;\n }\n\n dom.lastMessageSpan.classList.remove('user-typing');\n this.setLastMessage(dialog, null, dom);\n }\n}\n\nexport function generateVerifiedIcon() {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttributeNS(null, 'viewBox', '0 0 24 24');\n svg.setAttributeNS(null, 'width', '24');\n svg.setAttributeNS(null, 'height', '24');\n svg.classList.add('verified-icon');\n\n const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');\n use.setAttributeNS(null, 'href', '#verified-background');\n use.classList.add('verified-background');\n\n const use2 = document.createElementNS('http://www.w3.org/2000/svg', 'use');\n use2.setAttributeNS(null, 'href', '#verified-check');\n use2.classList.add('verified-check');\n\n svg.append(use, use2);\n\n return svg;\n}\n\nconst appDialogsManager = new AppDialogsManager();\nMOUNT_CLASS_TO.appDialogsManager = appDialogsManager;\nexport default appDialogsManager;\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport InputField from \"../inputField\";\nimport lottieLoader, { RLottiePlayer } from \"../../lib/lottieLoader\";\n\nexport default class TrackingMonkey {\n public container: HTMLElement;\n\n protected max = 45;\n protected needFrame = 0;\n\n protected animation: RLottiePlayer;\n protected idleAnimation: RLottiePlayer;\n\n protected loadPromise: Promise<any>;\n\n constructor(protected inputField: InputField, protected size: number) {\n this.container = document.createElement('div');\n this.container.classList.add('media-sticker-wrapper');\n\n const input = inputField.input;\n\n input.addEventListener('blur', () => {\n this.playAnimation(0);\n });\n\n input.addEventListener('input', (e) => {\n this.playAnimation(inputField.value.length);\n });\n\n /* codeInput.addEventListener('focus', () => {\n playAnimation(Math.max(codeInput.value.length, 1));\n }); */\n }\n\n // 1st symbol = frame 15\n // end symbol = frame 165\n public playAnimation(length: number) {\n if(!this.animation) return;\n\n length = Math.min(length, 30);\n let frame: number;\n if(length) {\n frame = Math.round(Math.min(this.max, length) * (165 / this.max) + 11.33);\n\n if(this.idleAnimation) {\n this.idleAnimation.stop(true);\n this.idleAnimation.canvas.style.display = 'none';\n }\n \n this.animation.canvas.style.display = '';\n } else {\n /* const cb = (frameNo: number) => {\n if(frameNo <= 1) { */\n /* idleAnimation.play();\n idleAnimation.canvas.style.display = '';\n animation.canvas.style.display = 'none'; */\n /* animation.removeListener('enterFrame', cb);\n }\n };\n animation.addListener('enterFrame', cb); */\n \n frame = 0;\n }\n //animation.playSegments([1, 2]);\n\n const direction = this.needFrame > frame ? -1 : 1;\n //console.log('keydown', length, frame, direction);\n\n this.animation.setDirection(direction);\n if(this.needFrame !== 0 && frame === 0) {\n this.animation.setSpeed(7);\n }\n /* let diff = Math.abs(needFrame - frame * direction);\n if((diff / 20) > 1) animation.setSpeed(diff / 20 | 0); */\n this.needFrame = frame;\n \n this.animation.play();\n\n /* animation.goToAndStop(15, true); */\n //animation.goToAndStop(length / max * );\n }\n\n public load() {\n if(this.loadPromise) return this.loadPromise;\n return this.loadPromise = Promise.all([\n lottieLoader.loadAnimationFromURL({\n container: this.container,\n loop: true,\n autoplay: true,\n width: this.size,\n height: this.size\n }, 'assets/img/TwoFactorSetupMonkeyIdle.tgs').then(animation => {\n this.idleAnimation = animation;\n\n // ! animationIntersector will stop animation instantly\n if(!this.inputField.value.length) {\n animation.play();\n }\n\n return lottieLoader.waitForFirstFrame(animation);\n }),\n\n lottieLoader.loadAnimationFromURL({\n container: this.container,\n loop: false,\n autoplay: false,\n width: this.size,\n height: this.size\n }, 'assets/img/TwoFactorSetupMonkeyTracking.tgs').then(_animation => {\n this.animation = _animation;\n\n if(!this.inputField.value.length) {\n this.animation.canvas.style.display = 'none';\n }\n\n this.animation.addEventListener('enterFrame', currentFrame => {\n //console.log('enterFrame', currentFrame, needFrame);\n //let currentFrame = Math.round(e.currentTime);\n \n if((this.animation.direction === 1 && currentFrame >= this.needFrame) ||\n (this.animation.direction === -1 && currentFrame <= this.needFrame)) {\n this.animation.setSpeed(1);\n this.animation.pause();\n }\n\n if(currentFrame === 0 && this.needFrame === 0) {\n //animation.curFrame = 0;\n \n if(this.idleAnimation) {\n this.idleAnimation.canvas.style.display = '';\n this.idleAnimation.play();\n this.animation.canvas.style.display = 'none';\n }\n }\n });\n //console.log(animation.getDuration(), animation.getDuration(true));\n\n return lottieLoader.waitForFirstFrame(_animation);\n })\n ]);\n }\n\n public remove() {\n if(this.animation) this.animation.remove();\n if(this.idleAnimation) this.idleAnimation.remove();\n }\n}\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport InputField, { InputFieldOptions } from \"./inputField\";\n\nexport default class CodeInputField extends InputField {\n constructor(options: InputFieldOptions & {\n length: number,\n onFill: (code: number) => void\n }) {\n super({\n plainText: true,\n ...options\n });\n\n const input = this.input as HTMLInputElement;\n input.type = 'tel';\n input.setAttribute('required', '');\n input.autocomplete = 'off';\n\n let lastLength = 0;\n this.input.addEventListener('input', (e) => {\n this.input.classList.remove('error');\n this.setLabel();\n \n const value = this.value.replace(/\\D/g, '').slice(0, options.length);\n this.setValueSilently(value);\n \n const length = this.value.length;\n if(length === options.length) { // submit code\n options.onFill(+this.value);\n } else if(length === lastLength) {\n return;\n }\n \n lastLength = length;\n });\n }\n}\n"],"sourceRoot":""}