mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-11 23:38:29 +01:00
1 line
889 KiB
Plaintext
1 line
889 KiB
Plaintext
{"version":3,"sources":["webpack:///./src/components/mediaViewer/helpers/ghostAnimation.ts","webpack:///./src/components/mediaViewer/SenderInfo.tsx","webpack:///./src/components/mediaViewer/MediaViewerActions.tsx","webpack:///./src/components/mediaViewer/MediaViewerFooter.tsx","webpack:///./src/hooks/useFullscreen.ts","webpack:///./src/components/mediaViewer/helpers/formatFileSize.ts","webpack:///./src/components/mediaViewer/VideoPlayerControls.tsx","webpack:///./src/components/mediaViewer/VideoPlayer.tsx","webpack:///./src/components/mediaViewer/ZoomControls.tsx","webpack:///./src/components/mediaViewer/PanZoom.tsx","webpack:///./src/components/mediaViewer/MediaViewer.tsx","webpack:///./src/hooks/useBlurSync.ts","webpack:///./src/components/main/ForwardPicker.tsx","webpack:///./src/components/main/Errors.tsx","webpack:///./src/components/main/Notifications.tsx","webpack:///./src/components/common/CalendarModal.tsx","webpack:///./src/components/common/DeleteMessageModal.tsx","webpack:///./src/components/common/PinMessageModal.tsx","webpack:///./src/components/common/UnpinAllMessagesModal.tsx","webpack:///./src/components/middle/DeleteSelectedMessagesModal.tsx","webpack:///./src/components/middle/MessageSelectToolbar.tsx","webpack:///./src/components/left/search/LeftSearchResultChat.tsx","webpack:///./src/components/left/search/RecentContacts.tsx","webpack:///./src/components/left/search/ChatMessage.tsx","webpack:///./src/components/left/search/DateSuggest.tsx","webpack:///./src/components/left/search/ChatResults.tsx","webpack:///./src/components/left/search/ChatMessageResults.tsx","webpack:///./src/components/left/search/helpers/createMapStateToProps.ts","webpack:///./src/components/left/search/MediaResults.tsx","webpack:///./src/components/left/search/helpers/getSenderName.ts","webpack:///./src/components/left/search/LinkResults.tsx","webpack:///./src/components/left/search/FileResults.tsx","webpack:///./src/components/left/search/AudioResults.tsx","webpack:///./src/components/left/search/LeftSearch.tsx","webpack:///./src/hooks/useReducer.ts","webpack:///./src/hooks/reducers/useFoldersReducer.ts","webpack:///./src/hooks/reducers/useTwoFaReducer.ts","webpack:///./src/components/left/settings/SettingsHeader.tsx","webpack:///./src/components/left/settings/SettingsMain.tsx","webpack:///./src/components/ui/FloatingActionButton.tsx","webpack:///./src/components/common/UsernameInput.tsx","webpack:///./src/components/left/settings/SettingsEditProfile.tsx","webpack:///./src/components/left/settings/folders/SettingsFoldersMain.tsx","webpack:///./src/components/ui/ShowMoreButton.tsx","webpack:///./src/components/left/settings/folders/SettingsFoldersEdit.tsx","webpack:///./src/components/left/settings/folders/SettingsFoldersChatsPicker.tsx","webpack:///./src/components/left/settings/folders/SettingsFoldersChatFilters.tsx","webpack:///./src/components/left/settings/folders/SettingsFolders.tsx","webpack:///./src/components/ui/RangeSlider.tsx","webpack:///./src/components/middle/composer/StickerSetCoverAnimated.tsx","webpack:///./src/components/middle/composer/StickerSetCover.tsx","webpack:///./src/components/common/StickerButton.tsx","webpack:///./src/components/left/settings/SettingsStickerSet.tsx","webpack:///./src/components/left/settings/SettingsGeneral.tsx","webpack:///./src/util/systemFilesDialog.ts","webpack:///./src/util/colors.ts","webpack:///./src/components/left/settings/WallpaperTile.tsx","webpack:///./src/components/left/settings/SettingsGeneralBackground.tsx","webpack:///./src/components/left/settings/SettingsGeneralBackgroundColor.tsx","webpack:///./src/components/left/settings/SettingsNotifications.tsx","webpack:///./src/components/left/settings/SettingsPrivacy.tsx","webpack:///./src/components/left/settings/SettingsLanguage.tsx","webpack:///./src/components/left/settings/helper/privacy.ts","webpack:///./src/components/left/settings/SettingsPrivacyVisibility.tsx","webpack:///./src/components/left/settings/SettingsPrivacyActiveSessions.tsx","webpack:///./src/components/left/settings/SettingsPrivacyBlockedUsers.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaEnabled.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaPassword.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaStart.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaSkippableForm.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaCongratulations.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFaEmailCode.tsx","webpack:///./src/components/left/settings/twoFa/SettingsTwoFa.tsx","webpack:///./src/components/common/Picker.tsx","webpack:///./src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx","webpack:///./src/components/left/settings/Settings.tsx","webpack:///./src/components/left/main/ContactList.tsx","webpack:///./src/components/left/newChat/NewChatStep1.tsx","webpack:///./src/components/left/newChat/NewChatStep2.tsx","webpack:///./src/components/left/newChat/NewChat.tsx","webpack:///./src/components/left/ArchivedChats.tsx","webpack:///./src/util/scrollLock.ts","webpack:///./src/components/middle/message/helpers/copyOptions.ts","webpack:///./src/components/middle/message/MessageContextMenu.tsx","webpack:///./src/components/middle/message/ContextMenuContainer.tsx","webpack:///./src/components/common/StickerSetModal.tsx","webpack:///./src/components/middle/HeaderMenuContainer.tsx","webpack:///./src/components/middle/MobileSearch.tsx","webpack:///./src/util/isFullyVisible.ts","webpack:///./src/components/middle/composer/MentionMenu.tsx","webpack:///./src/util/findInViewport.ts","webpack:///./src/components/middle/composer/AttachmentModal.tsx","webpack:///./src/components/middle/composer/PollModal.tsx","webpack:///./src/hooks/useMouseInside.ts","webpack:///./src/components/middle/composer/EmojiButton.tsx","webpack:///./src/components/middle/composer/EmojiCategory.tsx","webpack:///./src/components/middle/composer/EmojiPicker.tsx","webpack:///./src/components/middle/composer/StickerSet.tsx","webpack:///./src/components/middle/composer/StickerPicker.tsx","webpack:///./src/components/common/GifButton.tsx","webpack:///./src/components/middle/composer/GifPicker.tsx","webpack:///./src/components/middle/composer/SymbolMenuFooter.tsx","webpack:///./src/components/middle/composer/SymbolMenu.tsx","webpack:///./src/components/middle/composer/AttachMenu.tsx","webpack:///./src/components/middle/composer/EmojiTooltip.tsx","webpack:///./src/components/middle/composer/BotKeyboardMenu.tsx","webpack:///./src/components/middle/composer/CustomSendMenu.tsx","webpack:///./src/components/right/RightSearch.tsx","webpack:///./src/components/right/StickerSetResult.tsx","webpack:///./src/components/right/StickerSearch.tsx","webpack:///./src/components/right/GifSearch.tsx","webpack:///./src/components/right/Statistics.tsx","webpack:///./src/components/right/PollAnswerResults.tsx","webpack:///./src/components/right/PollResults.tsx","webpack:///./src/components/right/management/ManageUser.tsx","webpack:///./src/components/right/management/ManageGroup.tsx","webpack:///./src/components/right/management/ManageGroupPermissions.tsx","webpack:///./src/components/right/management/ManageGroupRemovedUsers.tsx","webpack:///./src/components/right/management/ManageChannel.tsx","webpack:///./src/components/right/management/ManageChatPrivacyType.tsx","webpack:///./src/components/right/management/ManageDiscussion.tsx","webpack:///./src/components/right/management/ManageGroupUserPermissions.tsx","webpack:///./src/components/right/management/ManageChatAdministrators.tsx","webpack:///./src/components/right/management/ManageGroupRecentActions.tsx","webpack:///./src/components/right/management/ManageGroupAdminRights.tsx","webpack:///./src/components/right/management/ManageGroupMembers.tsx","webpack:///./src/components/right/management/ManageGroupUserPermissionsCreate.tsx","webpack:///./src/components/right/management/Management.tsx","webpack:///./src/components/middle/helpers/getCurrencySign.ts","webpack:///./src/components/common/helpers/detectCardType.ts","webpack:///./src/hooks/reducers/usePaymentReducer.ts","webpack:///./src/hooks/useFocusAfterAnimation.tsx","webpack:///./src/components/ui/Select.tsx","webpack:///./src/components/payment/ShippingInfo.tsx","webpack:///./src/components/payment/Shipping.tsx","webpack:///./src/components/payment/Checkout.tsx","webpack:///./src/components/payment/ExpiryInput.tsx","webpack:///./src/components/middle/helpers/inputFormatters.ts","webpack:///./src/assets/mastercard.svg","webpack:///./src/assets/visa.svg","webpack:///./src/components/payment/CardInput.tsx","webpack:///./src/components/payment/PaymentInfo.tsx","webpack:///./src/components/payment/PaymentModal.tsx","webpack:///./src/components/payment/ReceiptModal.tsx","webpack:///./src/components/common/helpers/animatedAssets.ts","webpack:///./src/assets/TwoFactorSetupMonkeyIdle.tgs","webpack:///./src/assets/TwoFactorSetupMonkeyTracking.tgs","webpack:///./src/assets/TwoFactorSetupMonkeyClose.tgs","webpack:///./src/assets/TwoFactorSetupMonkeyPeek.tgs","webpack:///./src/assets/FoldersAll.tgs","webpack:///./src/assets/FoldersNew.tgs","webpack:///./src/assets/DiscussionGroupsDucks.tgs","webpack:///./src/components/ui/CropModal.tsx","webpack:///./src/components/ui/AvatarEditable.tsx","webpack:///./src/components/common/PasswordMonkey.tsx","webpack:///./src/components/common/PasswordForm.tsx"],"names":["animateOpening","hasFooter","origin","bestImageData","message","mediaEl","fromImage","getNodes","width","windowWidth","windowSize","get","mediaSize","isVideo","photo","video","webPage","getMessageContent","Boolean","getVideoDimensions","getPhotoFullDimensions","AVATAR_FULL_DIMENSIONS","availableWidth","height","availableHeight","getMediaViewerAvailableDimensions","toWidth","toHeight","calculateDimensions","toLeft","toTop","mql","window","matchMedia","MEDIA_VIEWER_MEDIA_QUERY","topOffsetRem","matches","REM","getTopOffset","top","fromTop","left","fromLeft","fromWidth","fromHeight","getBoundingClientRect","MediaViewerOrigin","SharedMedia","Album","ScheduledAlbum","SearchResult","includes","uncovered","realWidth","realHeight","size","Math","max","srcWidth","srcHeight","uncover","fromTranslateX","fromTranslateY","fromScaleX","fromScaleY","ghost","createGhost","applyStyles","transform","applyShape","document","body","classList","add","requestAnimationFrame","appendChild","style","firstChild","objectFit","remove","clearShape","setTimeout","removeChild","ANIMATION_END_DELAY","animateClosing","container","toImage","getElementById","querySelector","targetTop","el","display","rect","windowHeight","isElementInViewport","shouldFadeOut","Inline","ScheduledInline","isMessageImageFullyVisible","opacity","source","createElement","img","Image","src","HTMLVideoElement","poster","imageEl","messageListElement","imgOffsetTop","offsetTop","closest","id","parentElement","scrollTop","offsetHeight","element","styles","Object","assign","containerSelector","mediaSelector","MiddleHeaderAvatar","ProfileAvatar","mediaEls","querySelectorAll","length","withGlobal","global","chatId","messageId","isAvatar","sender","isChatPrivate","selectUser","selectChat","selectChatMessage","selectSender","setGlobal","actions","pick","closeMediaViewer","focusMessage","handleFocusMessage","useCallback","useLang","isFromChat","senderTitle","getSenderTitle","className","onClick","Avatar","key","chat","user","renderText","formatMediaDateTime","date","MediaViewerActions","mediaData","isZoomed","fileName","onCloseMediaViewer","onForward","onZoomToggle","isVideoDownloadAllowed","setIsVideoDownloadAllowed","useState","videoMediaHash","getMessageMediaHash","undefined","videoBlobUrl","downloadProgress","useMediaWithDownloadProgress","useEffect","download","handleVideoDownloadClick","e","stopPropagation","isAllowed","lang","MenuButton","useMemo","onTrigger","isOpen","Button","round","color","ariaLabel","IS_MOBILE_SCREEN","DropdownMenu","trigger","positionX","MenuItem","icon","href","ProgressSpinner","progress","noCross","MediaViewerFooter","text","isHideable","isMultiline","setIsMultiline","footerContent","checkIsMultiline","clientHeight","handleResize","throttle","addEventListener","removeEventListener","prop","fullscreenElement","mozFullScreenElement","webkitFullscreenElement","getBrowserFullscreenElementProp","units","bytes","number","floor","log","toFixed","stopEvent","VideoPlayerControls","bufferedProgress","currentTime","duration","fileSize","isForceVisible","isForceMobileVersion","isPlayed","isFullscreenSupported","isFullscreen","onChangeFullscreen","onPlayPause","onSeek","isVisible","setVisibility","timeout","clearTimeout","downloadedPercent","totalSize","percentagePlayed","percentageBuffered","min","step","type","onInput","value","renderSeekLine","ripple","formatMediaDuration","renderTime","formatFileSize","memo","url","isGif","posterData","posterSize","isMediaViewerOpen","noPlay","onClose","videoRef","useRef","setIsPlayed","IS_TOUCH_ENV","IS_IOS","setCurrentTime","isControlsVisible","setIsControlsVisible","setFullscreen","exitFullscreen","elRef","setIsFullscreen","useLayoutEffect","listener","listenerEnter","listenerExit","current","PLATFORM_ENV","requestFullscreen","webkitRequestFullscreen","webkitEnterFullscreen","mozRequestFullScreen","mozCancelFullScreen","webkitCancelFullScreen","webkitExitFullscreen","useFullscreenStatus","isBuffered","bufferingHandlers","useBuffering","shouldRender","shouldRenderSpinner","transitionClassNames","spinnerClassNames","useShowTransition","pause","safePlay","togglePlayState","play","useVideoCleanup","handleMouseOver","handleMouseOut","handleTimeUpdate","currentTarget","handleEnded","handleFullscreenChange","handleSeek","Number","target","toggleControls","togglePayingStateBySpace","wrapperStyle","videoStyle","onMouseOver","onMouseOut","ref","autoPlay","playsInline","loop","muted","onEnded","onTimeUpdate","join","square","isShown","onChangeZoom","prevIsShown","usePrevious","inputRef","zoomLevel","setZoomLevel","isSeeking","handleStartSeek","handleStopSeek","buildClassName","disabled","onChange","onMouseDown","onMouseUp","INITIAL_MATRIX","SCALE_VALUES","1","1.5","2","2.5","3","children","noWrap","canPan","panDeltaX","panDeltaY","onPan","tunedZoomLevel","isDragging","setIsDragging","dragData","setDragData","dx","dy","x","y","matrixData","setMatrixData","panWrapperRef","panContainerRef","newZoomLevel","newPandx","newPandy","newMatrixData","areSortedArraysEqual","oldScale","wrapper","image","wrapperRect","imageRect","newImgWidth","newImgHeight","newImgX","newImgY","calculateSafeZoneOnZoom","toString","preventDefault","newDragData","pageX","pageY","onMouseMove","deltaX","deltaY","getNewMatrixData","renderPhoto","blobUrl","imageSize","alt","draggable","Spinner","threadId","avatarOwnerId","mediaViewer","animationLevel","settings","byKey","senderId","avatarOwner","chatMessages","collectionIds","selectScheduledMessage","selectScheduledMessages","selectChatMessages","selectOutlyingIds","selectListedIds","currentSearch","selectCurrentMediaSearch","foundIds","resultsByType","media","openMediaViewer","openForwardMenu","animationKey","webPagePhoto","getMessageWebPagePhoto","getMessagePhoto","getMessageVideo","isWebPagePhoto","isPhoto","isFromSharedMedia","isFromSearch","slideAnimation","headerAnimation","isGhostAnimation","getMessageMediaFilename","prevSenderId","canPanZoomWrap","setCanPanZoomWrap","setIsZoomed","panDelta","setPanDelta","messageIds","getChatMediaMessageIds","selectedMediaMessageIndex","indexOf","isFirst","isLast","getMediaHash","full","getChatAvatarHash","blobUrlPictogram","useMedia","ApiMediaFormat","BlobUrl","blobUrlPreview","DataUri","fullMediaData","getMessageMediaFormat","localBlobUrl","thumbDataUri","dataUri","blurredRef","isChanged","useOnChange","canvas","imgToCanvas","fastBlur","getContext","toDataURL","blurredAsync","useBlur","useBlurSync","getMessageMediaThumbDataUri","photoDimensions","videoDimensions","toggle","forceUpdate","useForceUpdate","addListener","removeListener","prevMessage","prevOrigin","prevAvatarOwner","prevBestImageData","dispatchHeavyAnimationEvent","textParts","renderMessageText","timer","closeZoom","handleZoomToggle","handleZoomValue","level","canCloseZoom","close","handleFooterClick","handleForward","fromChatId","captureEscKeyListener","stopCurrentAudio","getMessageId","fromId","direction","index","selectPreviousMedia","selectNextMedia","handleKeyDown","shouldCloseOnVideo","captureEvents","excludedClosestSelector","onSwipe","SwipeDirection","Right","Left","handlePan","renderSlide","isActive","calculateMediaViewerDimensions","renderSenderInfo","ShowTransition","Transition","activeKey","name","aria-label","chats","byId","chatsById","listIds","orderedPinnedIds","currentUserId","active","currentUser","setForwardChatId","exitForwardMode","loadMoreChats","filter","setFilter","focus","blur","chatArrays","prepareChatList","chatWithSelf","pinnedChats","otherChats","chatIds","searchWords","getChatTitle","map","viewportIds","getMore","useInfiniteScroll","handleFilterChange","modalHeader","InputText","placeholder","Modal","header","InfiniteScroll","items","onLoadMore","isDisabled","ListItem","PrivateChatInfo","userId","GroupChatInfo","Loading","getErrorHeader","error","isSlowMode","errors","dismissError","title","getReadableErrorText","isText","notifications","dismissNotification","Notification","onDismiss","WEEKDAY_LETTERS","isDisabledDay","year","month","day","minDate","maxDate","selectedDay","Date","fixedMinDate","getFullYear","getMonth","getDate","fixedMaxDate","formatInputTime","String","padStart","selectedAt","maxAt","isFutureMode","isPastMode","withTimePicker","submitButtonLabel","secondButtonLabel","onSubmit","onSecondButtonClick","now","defaultSelectedDate","selectedDate","setSelectedDate","selectedHours","setSelectedHours","getHours","selectedMinutes","setSelectedMinutes","getMinutes","currentYear","currentMonth","currentDate","shouldDisableNextMonth","shouldDisablePrevMonth","calendarGrid","grid","setFullYear","setMonth","setDate","monthStartDay","getDay","i","push","gridDate","buildCalendarGrid","handleChangeHours","replace","hours","getTime","setHours","hoursStr","handleChangeMinutes","minutes","setMinutes","minutesStr","formatMonthAndYear","d","dateCopy","letter","role","tabIndex","handleDateSelect","inputMode","formatHumanDate","formatTime","formatSubmitLabel","isSchedule","selectCurrentMessageList","canDeleteForAll","selectAllowedMessageActions","contactName","getUserFirstOrLastName","getPrivateChatUserId","willDeleteForCurrentUserOnly","isChatBasicGroup","willDeleteForAll","isChatSuperGroup","album","deleteMessages","deleteScheduledMessages","handleDeleteMessageForAll","messages","shouldDeleteForAll","handleDeleteMessageForSelf","onEnter","isPrivateChat","isChatWithSelf","selectIsChatWithSelf","isChannel","isChatChannel","isGroup","isSuperGroup","canPinForAll","pinMessage","handlePinMessageForAll","isUnpin","handlePinMessage","isOneSide","isSilent","pinnedIds","selectPinnedIds","pinnedMessagesCount","onUnpin","selectedMessageIds","selectedMessages","selectCanDeleteSelectedMessages","selectCurrentChat","exitMessageSelectMode","messageListType","canDelete","selectedMessagesCount","selectSelectedMessagesCount","canDeleteMessages","canPost","openForwardMenuForSelectedMessages","isDeleteModalOpen","openDeleteModal","closeDeleteModal","useFlag","captureKeyboardListeners","onBackspace","onDelete","onEsc","prevSelectedMessagesCount","renderingSelectedMessagesCount","formattedMessagesCount","destructive","privateChatUserId","privateChatUser","isPinned","selectIsChatPinned","withHandle","contextActions","useChatContextActions","handleDelete","avatarSize","DeleteChatModal","runThrottled","cb","userIds","topUserIds","topPeers","usersById","users","recentlyFoundChatIds","globalSearch","onReset","loadTopUsers","loadContactList","openChat","addRecentlyFoundChatId","clearRecentlyFoundChats","topUsersRef","useHorizontalScroll","handleClick","lastSyncTime","searchQuery","mediaThumbnail","mediaBlobUrl","withOnlineStatus","isSavedMessages","isSelf","isVerified","VerifiedIcon","Link","formatPastTimeShort","getMessageSummaryText","highlight","renderMessageSummary","searchDate","onSelect","suggestions","match","formatDateToString","suggestion","latestYear","getSuggestionsFromDate","sortSearchResults","a","b","localContactIds","contactList","fetchingStatus","globalResults","localResults","globalChats","globalUsers","localChats","localUsers","byChatId","globalMessagesByChatId","dateSearchQuery","onSearchDateSelect","searchMessagesGlobal","setGlobalSearchChatId","shouldShowMoreLocal","setShouldShowMoreLocal","shouldShowMoreGlobal","setShouldShowMoreGlobal","handleLoadMore","LoadMoreDirection","Backwards","query","handleChatClick","handlePickerItemClick","startsWith","MEMO_EMPTY_ARRAY","foundLocalContacts","fullName","getUserFullName","username","unique","getTranslation","sort","foundMessages","split","handleClickShowMoreLocal","handleClickShowMoreGlobal","nothingFound","noFastList","NothingFound","PickerSelectedItem","chatOrUserId","clickArg","createMapStateToProps","props","currentType","isVoice","isLoading","searchChatId","handleSelectMedia","canRenderContents","useAsyncRendering","SLIDE_TRANSITION_DURATION","isMediaGrid","isMessageList","classNames","itemSelector","Media","idPrefix","getSenderName","senderName","isChatGroup","handleMessageFocus","shouldDrawDateDivider","toYearMonth","WebLink","onMessageClick","getMessageDocument","Document","withDate","datetime","smaller","onDateClick","openAudioPlayer","handlePlayAudio","Audio","renderingFor","onPlay","TABS","GlobalSearchContent","ChatList","Links","Files","Music","Voice","CHAT_TABS","slice","TRANSITION_RENDER_COUNT","keys","currentContent","setGlobalSearchContent","setGlobalSearchDate","activeTab","setActiveTab","parseDateString","handleSwitchTab","tab","content","handleSearchDateSelect","TabList","tabs","onSwitchTab","renderCount","useReducer","reducer","initialState","reducerRef","state","setState","action","currentState","INCLUDED_CHAT_TYPES","EXCLUDED_CHAT_TYPES","INCLUDE_FILTER_FIELDS","EXCLUDE_FILTER_FIELDS","selectChatFilters","mode","selectTemp","selectedChatIds","selectedChatTypes","includedChatIds","includeFilters","folder","excludedChatIds","excludeFilters","getSuggestedFolderName","filters","values","bots","groups","channels","contacts","nonContacts","INITIAL_STATE","chatFilter","foldersReducer","payload","isTouched","omit","folderId","description","currentPassword","password","hint","email","twoFaReducer","currentScreen","editedFolderId","onSaveFilter","signOut","deleteChatFolder","isSignOutDialogOpen","setIsSignOutDialogOpen","isDeleteFolderDialogOpen","setIsDeleteFolderDialogOpen","openSignOutConfirmation","closeSignOutConfirmation","openDeleteFolderConfirmation","closeDeleteFolderConfirmation","handleSignOutMessage","handleDeleteFolderMessage","SettingsMenuButton","SettingsScreens","EditProfile","General","Notifications","Privacy","Language","GeneralChatBackground","GeneralChatBackgroundColor","PrivacyPhoneNumber","PrivacyLastSeen","PrivacyProfilePhoto","PrivacyForwarding","PrivacyGroupChats","PrivacyPhoneNumberAllowedContacts","PrivacyLastSeenAllowedContacts","PrivacyProfilePhotoAllowedContacts","PrivacyForwardingAllowedContacts","PrivacyGroupChatsAllowedContacts","PrivacyPhoneNumberDeniedContacts","PrivacyLastSeenDeniedContacts","PrivacyProfilePhotoDeniedContacts","PrivacyForwardingDeniedContacts","PrivacyGroupChatsDeniedContacts","PrivacyActiveSessions","PrivacyBlockedUsers","TwoFaDisabled","TwoFaEnabled","TwoFaNewPassword","TwoFaChangePasswordNew","TwoFaChangePasswordConfirm","TwoFaNewPasswordConfirm","TwoFaNewPasswordHint","TwoFaChangePasswordHint","TwoFaNewPasswordEmail","TwoFaRecoveryEmail","TwoFaNewPasswordEmailCode","TwoFaRecoveryEmailCode","TwoFaCongratulations","TwoFaChangePasswordCurrent","TwoFaTurnOff","TwoFaRecoveryEmailCurrentPassword","Folders","FoldersCreateFolder","FoldersEditFolder","FoldersIncludedChats","FoldersExcludedChats","renderHeaderContent","ConfirmDialog","confirmLabel","confirmHandler","confirmIsDestructive","onScreenSelect","formatPhoneNumberWithCode","phoneNumber","FloatingActionButton","buttonClassName","LINK_PREFIX_REGEX","USERNAME_REGEX","runDebouncedForCheckUsername","debounce","currentUsername","asLink","isUsernameAvailable","checkUsername","setUsername","langPrefix","label","usernameSuccess","usernameError","test","handleUsernameChange","newUsername","trim","isValid","isUsernameValid","success","readOnly","profileEdit","firstName","currentFirstName","lastName","currentLastName","fullInfo","bio","currentBio","currentAvatarHash","loadCurrentUser","updateProfile","isUsernameTouched","setIsUsernameTouched","isProfileFieldsTouched","setIsProfileFieldsTouched","setError","setPhoto","setFirstName","setLastName","setBio","currentAvatarBlobUrl","ProfileEditProgress","InProgress","isUsernameError","isSaveButtonShown","Complete","handlePhotoChange","newPhoto","handleFirstNameChange","handleLastNameChange","handleBioChange","handleProfileSave","trimmedFirstName","trimmedLastName","trimmedBio","AvatarEditable","UsernameInput","runThrottledForLoadRecommended","orderedIds","orderedFolderIds","foldersById","recommended","recommendedChatFolders","chatFolders","onCreateFolder","onEditFolder","loadRecommendedChatFolders","addChatFolder","showError","animationData","setAnimationData","isAnimationLoaded","setIsAnimationLoaded","handleAnimationLoad","getAnimationData","then","handleCreateFolder","userFolders","subtitle","getFolderDescriptionText","handleCreateFolderFromRecommended","AnimatedSticker","STICKER_SIZE_FOLDER_SETTINGS","noLoop","onLoad","pill","fluid","narrow","ShowMoreButton","count","itemName","itemPluralName","ERROR_NO_TITLE","ERROR_NO_CHATS","loadedActiveChatIds","loadedArchivedChatIds","archived","dispatch","onAddIncludedChats","onAddExcludedChats","editChatFolder","isIncludedChatsListExpanded","setIsIncludedChatsListExpanded","isExcludedChatsListExpanded","setIsExcludedChatsListExpanded","includedChatTypes","excludedChatTypes","visibleIncludedChatIds","visibleExcludedChatIds","allLoadedChatsSet","Set","loadedIncludedChatIds","findIntersectionWithSet","loadedExcludedChatIds","listType","renderChats","visibleChatIds","isExpanded","leftChatsCount","clickHandler","chatType","find","typeKey","inactive","renderChatType","event","folderUpdate","selectedIds","filterValue","onSelectedIdsChange","onSelectedChatTypesChange","onFilterChange","chatTypes","shouldMinimize","hasMaxChats","handleItemClick","newSelectedIds","splice","handleChatTypeClick","newSelectedChatTypes","selectedType","isMinimized","canClose","Checkbox","checked","isSelected","withChatType","archivedPinnedIds","archivedListIds","activeChatArrays","archivedChatArrays","displayedIds","newFilter","handleSelectedIdsChange","ids","handleSelectedChatTypesChange","newFilters","forEach","handleReset","handleEditFolder","handleAddIncludedChats","handleAddExcludedChats","options","range","handleChange","trackWidth","possibleValuesLength","option","STICKER_SIZE_PICKER_HEADER","stickerSet","observeIntersection","isIntersecting","useIsIntersecting","mediaHash","lottieData","Lottie","shouldRenderFullMedia","useTransitionForMedia","getFirstLetters","hasThumbnail","sticker","noAnimate","onUnfaveClick","isAnimated","localMediaHash","stickerSelector","thumbnail","previewBlobUrl","shouldPlay","markLoaded","unmarkLoaded","canAnimatedPlay","shouldRenderThumb","shouldRenderPreview","previewTransitionClassNames","fullClassName","emoji","data-sticker-id","isLowPriority","stickers","firstSticker","STICKER_SIZE_GENERAL_SETTINGS","KEYBOARD_SEND_OPTIONS","subLabel","IS_MAC_OS","ANIMATION_LEVEL_OPTIONS","stickerSetIds","added","setIds","stickerSetsById","setsById","messageTextSize","messageSendKeyCombo","shouldAutoDownloadMediaFromContacts","shouldAutoDownloadMediaInPrivateChats","shouldAutoDownloadMediaInGroups","shouldAutoDownloadMediaInChannels","shouldAutoPlayGifs","shouldAutoPlayVideos","shouldSuggestStickers","shouldLoopStickers","setSettingOption","loadStickerSets","loadAddedStickers","stickerSettingsRef","observe","observeIntersectionForCovers","useIntersectionObserver","rootRef","isModalOpen","openModal","closeModal","setSticker","handleAnimationLevelChange","newLevel","_","handleMessageTextSizeChange","newSize","documentElement","setProperty","handleStickerSetClick","stickerSets","installedDate","RadioGroup","selected","onCheck","isChecked","fromSticker","fileSelector","openSystemFilesDialog","accept","callback","noMultiple","setAttribute","removeAttribute","onchange","click","hex2rgb","param","parseInt","substring","rgb2hex","p0","p1","p2","rgb2hsb","r","g","h","s","v","hsb2rgb","f","p","q","t","getPatternColor","rgbColor","hue","saturation","wallpaper","slug","isDownloadAllowed","setIsDownloadAllowed","fullMedia","wasDownloadDisabled","UPLOADING_WALLPAPER_SLUG","handleSelect","blob","fetchBlob","cacheApi","CUSTOM_BG_CACHE_NAME","isBackgroundBlurred","customBackground","loadedWallpapers","loadWallpapers","uploadWallpaper","handleFileSelect","files","handleUploadWallpaper","handleSetColor","handleResetToDefault","patternColor","DEFAULT_PATTERN_COLOR","handleWallPaperSelect","currentWallpaper","async","defaultRGB","data","rgb","context","preloadImage","naturalHeight","naturalWidth","offsetWidth","drawImage","getImageData","blockSize","getAverageColor","handleWallPaperBlurChange","isUploading","DEFAULT_HSB","PREDEFINED_COLORS","hsb2positions","hsb","rects","colorPosition","colorRect","huePosition","hueRect","positions2hsb","containerRef","colorPickerRef","huePickerRef","isFirstRunRef","setHsb","getInitialHsb","hsbRef","markIsDragging","unmarkIsDragging","rgbInput","setRgbInput","hexInput","setHexInput","rectsRef","colorCtxRef","offsetLeft","handleColorDrag","handleHueDrag","onCapture","onDrag","onRelease","withCursor","hex","hueHex","w","ctx","imgData","createImageData","pixels","col","perY","st","ed","perX","putImageData","drawColor","drawHue","handleRgbChange","rgbValue","channel","handleHexChange","hexValue","handlePredefinedColorClick","dataset","data-color","hasPrivateChatsNotifications","hasPrivateChatsMessagePreview","hasGroupNotifications","hasGroupMessagePreview","hasBroadcastNotifications","hasBroadcastMessagePreview","hasContactJoinedNotifications","loadNotificationsSettings","updateContactSignUpNotification","updateNotificationSettings","handleSettingsChange","peerType","setting","currentIsSilent","currentIsShowPreviews","isShowPreviews","handleContactNotificationChange","hasPassword","privacy","blocked","activeSessions","blockedCount","totalCount","sessionsCount","visibilityPrivacyPhoneNumber","visibility","visibilityPrivacyLastSeen","lastSeen","visibilityPrivacyProfilePhoto","profilePhoto","visibilityPrivacyForwarding","forwards","visibilityPrivacyGroupChats","chatInvite","loadPrivacySettings","loadBlockedContacts","loadAuthorizations","getVisibilityValue","languages","language","loadLanguages","selectedLanguage","setSelectedLanguage","markIsLoading","unmarkIsLoading","langCode","setLanguage","nativeName","buildOptions","loadingOption","getPrivacyKey","screen","privacySettings","allowUserIds","allowChatIds","blockUserIds","blockChatIds","setPrivacyVisibility","visibilityOptions","exceptionLists","shouldShowDenied","shouldShowAllowed","privacyKey","headerText","descriptionText","allowedContactsScreen","deniedContactsScreen","allowedCount","reduce","result","membersCount","blockCount","handleVisibilityChange","getLocation","session","region","country","getDeviceEnvironment","deviceModel","platform","systemVersion","terminateAuthorization","terminateAllAuthorizations","isConfirmTerminateAllDialogOpen","openConfirmTerminateAllDialog","closeConfirmTerminateAllDialog","handleTerminateSessionClick","hash","handleTerminateAllSessions","currentSession","isCurrent","otherSessions","renderSession","handler","dateActive","appName","ip","sessions","chatsByIds","usersByIds","blockedIds","unblockContact","handleUnblockClick","contactId","viewportOffset","isPrivate","CHAT_HEIGHT_PX","renderContact","animatedEmoji","selectAnimatedEmoji","AnimatedEmoji","expectedPassword","submitLabel","clearError","validationError","setValidationError","shouldShowPassword","setShouldShowPassword","handleSubmit","newPassword","handleClearError","PasswordMonkey","isBig","isPasswordVisible","PasswordForm","onChangePasswordVisibility","onStart","FOCUS_DELAY_TIMEOUT_MS","shouldConfirm","setValue","isConfirmShown","markIsConfirmShown","unmarkIsConfirmShown","codeLength","twoFaSettings","waitingEmailCodeLength","newValue","updatePassword","checkPassword","clearTwoFaError","updateRecoveryEmail","provideTwoFaEmailCode","clearPassword","handleStartWizard","handleNewPassword","handleNewPasswordConfirm","handleNewPasswordHint","handleNewPasswordEmail","onSuccess","handleChangePasswordCurrent","handleChangePasswordNew","handleChangePasswordConfirm","handleChangePasswordHint","handleTurnOff","handleRecoveryEmailCurrentPassword","handleRecoveryEmail","handleEmailCode","code","itemIds","filterPlaceholder","notFoundText","searchInputId","getCurrentPrivacySettings","isAllowList","setPrivacySettings","selectedContactIds","setSearchQuery","isSubmitShown","setIsSubmitShown","newSelectedContactIds","setNewSelectedContactIds","handleSelectedContactIdsChange","contactsIds","foldersState","foldersDispatch","twoFaState","twoFaDispatch","handleSaveFilter","renderCurrentSection","Main","renderCurrentSectionContent","contactIds","resultIds","getSortedUserIds","forceShowSelf","isSearching","selectedMemberIds","onSelectedMemberIdsChange","onNextStep","setGlobalSearchQuery","handleNextStep","creationProgress","creationError","chatCreation","memberIds","createGroupChat","createChannel","setTitle","about","setAbout","ChatCreationProgress","handleTitleChange","handleDescriptionChange","handleCreateGroup","handleCreateChannel","renderedError","RENDER_COUNT","LeftColumnContent","onContentChange","newChatMemberIds","setNewChatMemberIds","NewChannelStep2","NewGroupStep2","NewChannelStep1","NewGroupStep1","folderType","noChatsText","IGNORED_KEYS","Down","ArrowDown","Up","ArrowUp","ArrowLeft","ArrowRight","PageUp","PageDown","End","Home","Tab","preventDefaultForScrollKeys","disableScrolling","passive","ontouchmove","onkeydown","enableScrolling","getCopyLabel","hasSelection","canImageBeCopied","MessageContextMenu","anchor","canSendNow","canReschedule","canReply","canEdit","canPin","canUnpin","canForward","canFaveSticker","canUnfaveSticker","canCopy","canCopyLink","canSelect","onReply","onEdit","onPin","onFaveSticker","onUnfaveSticker","onSend","onReschedule","onCloseAnimationEnd","onCopyLink","copyOptions","afterEffect","getMessageText","CLIPBOARD_ITEM_SUPPORTED","selection","getSelection","mediaLoader","copyImageToClipboard","anchorNode","parentNode","clipboardText","copyTextToClipboard","getMessageCopyOptions","getTriggerElement","getRootElement","getMenuElement","positionY","useContextMenuPosition","Menu","noOptions","isScheduled","setReplyingToId","setEditingId","faveSticker","unfaveSticker","toggleMessageSelection","sendScheduledMessages","rescheduleMessage","loadMessageLink","isMenuOpen","setIsMenuOpen","setIsDeleteModalOpen","isPinModalOpen","setIsPinModalOpen","isCalendarOpen","openCalendar","closeCalendar","closeMenu","closePinModal","handleCloseCalendar","handleReply","handleEdit","handlePin","handleUnpin","handleFaveSticker","handleUnfaveSticker","handleSelectMessage","params","childMessageIds","withShift","handleScheduledMessageSend","handleOpenCalendar","handleRescheduleMessage","scheduledAt","handleCopyLink","scheduledMaxDate","getDayStartAt","selectStickerSet","stickerSetId","loadStickers","toggleStickerSet","sendMessage","throttleMs","stickerSetAccessHash","isPreloadedGlobally","handleButtonClick","hasCloseButton","STICKER_SIZE_MODAL","isRestricted","isMuted","canDeleteChat","getCanDeleteChat","canSubscribe","canSearch","canMute","canLeave","onSubscribeChannel","onSearchClick","updateChatMutedState","enterMessageSelectMode","handleToggleMuteClick","handleSubscribe","handleSearch","handleSelectMessages","Portal","runDebouncedForSearch","results","selectCurrentTextSearch","setLocalTextSearchQuery","searchTextMessagesLocal","closeLocalTextSearch","searchMessagesByDate","focusedIndex","setFocusedIndex","visualViewport","mainEl","activeElement","pageTop","Array","from","input","div","contentEditable","handleMessageSearchQueryChange","newQuery","handleJumpToDate","timestamp","valueOf","handleUp","newFocusIndex","handleDown","SearchInput","isFullyVisible","viewportY1","viewportY2","y1","y2","onInsertUserName","filteredChatMembers","getSelectedIndex","newIndex","cycleRestrict","selectedMentionIndex","setSelectedMentionIndex","handleArrowKey","handleUserSelect","forceFocus","handleSelectMention","member","onUp","onDown","onTab","visibleIndexes","allElements","selectorOrElements","margin","isDense","shouldContainBottom","isFound","findInViewport","first","position","fastSmoothScroll","setItemVisible","prevChatMembers","renderedChatMembers","attachments","caption","canSuggestMembers","groupChatMembers","onCaptionUpdate","onClear","prevAttachments","renderingAttachments","isMentionMenuOpen","mentionFilter","closeMentionMenu","insertMention","mentionFilteredMembers","useMentionMenu","EDITABLE_INPUT_MODAL_ID","sendAttachments","areAllPhotos","every","mimeType","areAllVideos","isQuick","quick","renderHeader","attachment","File","filename","extension","getFileExtension","previewData","MessageInput","html","editableInputId","onUpdate","shouldSetFocus","questionInputRef","optionsListRef","solutionRef","question","setQuestion","setOptions","isAnonymous","setIsAnonymous","isMultipleAnswers","setIsMultipleAnswers","isQuizMode","setIsQuizMode","solution","setSolution","correctOption","setCorrectOption","hasErrors","setHasErrors","focusInput","solutionEl","innerHTML","addNewOption","newOptions","list","scrollHeight","scrollTo","behavior","handleCreate","questionTrimmed","optionsTrimmed","o","summary","answers","correct","isPublic","multipleChoice","quiz","entities","parseMessageInput","correctAnswers","solutionEntities","updateOption","removeOption","handleCorrectOptionChange","handleIsAnonymousChange","handleMultipleAnswersChange","handleQuizModeChange","handleKeyPress","keyCode","getQuestionError","getOptionsError","renderOptions","onKeyPress","renderQuizNoOptionError","hidden","closeTimeout","useMouseInside","menuCloseTimeout","isMouseInside","native","colons","IS_EMOJI_SUPPORTED","loading","category","allEmojis","onEmojiSelect","useOnIntersect","emojisPerRow","ceil","emojis","displayedEmoji","ICONS_BY_CATEGORY","recent","people","nature","foods","activity","places","objects","symbols","flags","categoryIntersections","emojiDataPromise","emojiRawData","emojiData","recentEmojis","addRecentEmoji","headerRef","categories","setCategories","setEmojis","activeCategoryIndex","setActiveCategoryIndex","entries","entry","intersectingWithIndexes","newLeft","HEADER_BUTTON_WIDTH","fastSmoothScrollHorizontal","allCategories","themeCategories","unshift","exec","default","uncompressEmoji","ensureEmojiData","selectCategory","categoryEl","handleEmojiSelect","MENU_TRANSITION_DURATION","containerClassName","faded","STICKER_MARGIN","loadAndPlay","onStickerSelect","onStickerUnfave","stickersPerRow","STICKER_SIZE_PICKER","stickerSetIntersections","favorite","recentStickers","favoriteStickers","addedSetIds","canSendStickers","loadRecentStickers","loadFavoriteStickers","addRecentSticker","activeSetIndex","setActiveSetIndex","areAddedLoaded","allSets","noPopulatedSets","set","stickerSetEl","handleStickerSelect","handleStickerUnfave","gif","videoData","shouldRenderVideo","preload","savedGifs","gifs","saved","canSendGifs","onGifSelect","loadSavedGifs","debounceMs","SymbolMenuTabs","SYMBOL_MENU_TAB_TITLES","SYMBOL_MENU_TAB_ICONS","Emoji","Stickers","GIFs","onRemoveSymbol","onSearchOpen","renderTabButton","handleSearchOpen","isActivated","allowedAttachmentOptions","handleMouseEnter","handleMouseLeave","fastRaf","renderContent","isFrom","onMouseEnter","onMouseLeave","noCloseOnBackdrop","onFileSelect","onPollCreate","handleQuickSelect","CONTENT_TYPES_FOR_QUICK_UPLOAD","handleDocumentSelect","canAttachMedia","canAttachPolls","autoClose","forEmoji","clearStickersForEmoji","prevStickers","displayedStickers","clickInlineButton","keyboardButtons","row","button","onSilentSend","onScheduleSend","messagesById","foundResults","senderUser","getGlobal","senderChat","forwardInfo","isChannelPost","orderBy","preloadBackwards","LastMessageMeta","selectShouldLoopStickers","isSomeModalOpen","onModalToggle","isAdded","areStickersLoaded","coverStickerIds","covers","otherStickers","handleAddClick","canRenderStickers","STICKER_SIZE_SEARCH","selectCurrentStickerSearch","featured","featuredIds","loadFeaturedStickers","setIsModalOpen","selectCurrentGifSearch","isChatWithBot","selectIsChatWithBot","searchMoreGifs","setGifSearchQuery","getAllowedAttachmentOptions","handleGifClick","hasResults","lovelyChartPromise","LovelyChart","fetchJson","path","fetch","response","json","fetchDayData","dataSource","isReady","setIsReady","loadedChartsCount","setLoadedChartsCount","ensureLovelyChart","growth","create","onZoom","interactions","views","answer","voters","offsets","pollResults","offset","answerVote","totalVoters","loadPollOptionResults","closePollResults","prevVotersCount","votersCount","setIsLoading","areVotersLoaded","limit","shouldResetVoters","handleViewMoreClick","handleMemberClick","noStatusOrTyping","leftVotersCount","renderViewMoreButton","total","getMessagePoll","resultsByOption","buildCollectionByKey","management","updateContact","deleteUser","deleteHistory","closeManagement","isDeleteDialogOpen","openDeleteDialog","closeDeleteDialog","currentIsMuted","isNotificationsEnabled","setIsNotificationsEnabled","ManagementProgress","handleNotificationChange","handleDeleteContact","lastMessage","maxId","status","withMediaViewer","withFullInfo","hasLinkedChannel","linkedChatId","isBasicGroup","canChangeInfo","getHasAdminRight","canBanUsers","togglePreHistoryHidden","updateChat","leaveChannel","deleteChannel","currentTitle","currentAbout","imageHash","handleClickEditType","ManagementScreens","ChatPrivacyType","handleClickDiscussion","Discussion","handleClickPermissions","GroupPermissions","handleClickAdministrators","ChatAdministrators","handleSetPhoto","file","handleAboutChange","handleUpdateGroup","trimmedTitle","trimmedAbout","handleClickMembers","GroupMembers","handleTogglePreHistory","isPreHistoryHidden","isEnabled","enabledPermissionsCount","defaultBannedRights","sendStickers","sendGifs","adminsCount","adminMembers","handleDeleteGroup","isCreator","formatInteger","onChatMemberSelect","updateChatDefaultBannedRights","permissions","setPermissions","havePermissionChanged","setHavePermissionChanged","handleRemovedUsersClick","GroupRemovedUsers","handleAddExceptionClick","GroupUserPermissionsCreate","handleExceptionMemberClick","promotedByUserId","GroupUserPermissions","handlePermissionChange","getUpdatedPermissionValue","handleSavePermissions","bannedRights","removedUsersCount","kickedMembers","exceptionMembers","members","getMemberExceptions","langKey","getLangKeyForBannedRightKey","translatedString","sendMessages","blocking","sendMedia","sendPolls","embedLinks","inviteUsers","pinMessages","changeInfo","updateChatMemberBannedRights","removedMembers","getRemovedBy","kickedByUserId","kickedByUser","getContextActions","isSignaturesShown","toggleSignatures","hasLinkedChat","handleUpdateChannel","handleToggleSignatures","handleClickSubscribers","ChannelSubscribers","handleDeleteChannel","selectManagement","checkPublicLink","updatePublicLink","updatePrivateLink","privateLink","inviteLink","privacyType","setPrivacyType","isRevokeConfirmDialogOpen","openRevokeConfirmDialog","closeRevokeConfirmDialog","canUpdate","handleOptionChange","handleSave","handleRevokePrivateLink","langPrefix1","langPrefix2","SafeLink","forDiscussionIds","linkedChat","loadGroupsForDiscussion","linkDiscussionGroup","unlinkDiscussionGroup","linkedGroupId","setLinkedGroupId","isConfirmUnlinkGroupDialogOpen","openConfirmUnlinkGroupDialog","closeConfirmUnlinkGroupDialog","isConfirmLinkGroupDialogOpen","openConfirmLinkGroupDialog","closeConfirmLinkGroupDialog","handleUnlinkGroupSessions","channelId","Initial","handleLinkGroupSessions","renderLinkGroupHeader","linkedGroup","renderLinkGroupConfirmText","hasPrivateLink","STICKER_SIZE_DISCUSSION_GROUPS","teactFastList","teactOrderKey","isButtonsInOneRow","isPromotedByCurrentUser","isFormFullyDisabled","selectedChatMemberId","isBanConfirmationDialogOpen","openBanConfirmationDialog","closeBanConfirmationDialog","selectedChatMember","handleBanFromGroup","viewMessages","getControlIsDisabled","isOwner","handleAdminMemberClick","ChatAdminRights","getMemberStatus","promotedByUser","GroupRecentActions","updateChatAdmin","setIsTouched","isDismissConfirmationDialogOpen","openDismissConfirmationDialog","closeDismissConfirmationDialog","customTitle","setCustomTitle","adminRights","substr","handleDismissAdmin","memberStatus","handleCustomTitleChange","postMessages","editMessages","banUsers","addAdmins","anonymous","maxLength","openUserInfo","memberId","managementType","selectCurrentManagementType","CURRENCIES","USD","EUR","GBP","JPY","RUB","UAH","INR","AED","getCurrencySign","currency","VISA","MASTERCARD1","MASTERCARD2","CardType","cards","Default","Visa","Mastercard","detectCardType","cardNumber","streetLine1","streetLine2","city","countryIso2","postCode","phone","shipping","cardholder","expiry","cvv","billingCountry","billingZip","saveInfo","saveCredentials","formErrors","getBillingCountry","countryCode","countryList","useFocusAfterAnimation","animationDuration","hasArrow","labelText","htmlFor","needEmail","needPhone","needName","needAddress","phoneRef","selectCountryRef","handleAddress1Change","handleAddress2Change","handleCityChange","handleStateChange","handleCountryChange","handlePostCodeChange","handleFullNameChange","handleEmailChange","handlePhoneChange","handleSaveInfoChange","shippingOptions","handleShippingSelect","amount","renderPaymentItem","main","renderCheckoutItem","invoiceContent","prices","shippingPrices","checkoutInfo","totalPrice","photoUrl","paymentMethod","paymentProvider","shippingAddress","shippingMethod","item","expiryInputRef","charAt","parts","formatCardExpiry","onKeyDown","cardNumberRef","cardType","setCardType","newCardType","formatCardNumber","cardIcon","mastercardIconPath","visaIconPath","getCardIcon","canSaveCredentials","needCardholderName","needCountry","needZip","handleCardNumberChange","handleCardholderChange","toUpperCase","handleExpiryChange","handleCvvChange","handleBillingPostCodeChange","handleChangeSaveCredentials","savedInfo","invoice","nativeProvider","nativeParams","passwordMissing","payment","isProviderError","nameRequested","phoneRequested","emailRequested","shippingAddressRequested","flexible","phoneToProvider","emailToProvider","globalErrors","validateRequestedInfo","sendPaymentForm","setPaymentStep","sendCredentialsInfo","clearPaymentError","paymentState","paymentDispatch","currencySign","field","fieldError","getShippingError","handleErrorModalClose","PaymentStep","Checkout","shippingOption","getShippingPrices","totalPrices","concat","acc","cur","getTotalPrice","detectCardTypeText","findShippingOption","getCheckoutInfo","validateRequest","requestInfo","getRequestInfo","sendCredentials","credentials","expiryMonth","expiryYear","zip","getCredentials","sendForm","shippingOptionId","setStep","nextStep","ShippingInfo","Shipping","PaymentInfo","buttonText","cuurentStep","renderModalContent","renderError","optionId","receipt","mapedPrices","info","totalAmount","credentialsTitle","fullAddress","ANIMATED_STICKERS_PATHS","MonkeyIdle","MonkeyTracking","MonkeyClose","MonkeyPeek","FoldersAll","FoldersNew","DiscussionGroups","location","cropperResultOptions","quality","format","circle","Croppie","croppiePromise","cropper","isCroppieReady","setIsCroppieReady","imgFile","cropContainer","enableZoom","boundary","viewport","blobToDataUri","bind","err","DEBUG","console","initCropper","ensureCroppie","croppedImg","blobToFile","selectedFile","setSelectedFile","croppedBlobUrl","setCroppedBlobUrl","labelClassName","URL","revokeObjectURL","createObjectURL","SEGMENT_COVER_EYES","SEGMENT_UNCOVER_EYE","SEGMENT_COVER_EYE","STICKER_SIZE","STICKER_SIZE_AUTH_MOBILE","STICKER_SIZE_AUTH","closeMonkeyData","setCloseMonkeyData","peekMonkeyData","setPeekMonkeyData","isFirstMonkeyLoaded","setIsFirstMonkeyLoaded","isPeekShown","setIsPeekShown","handleFirstMonkeyLoad","STICKER_SIZE_TWO_FA","playSegment","onInputChange","setPassword","canSubmit","setCanSubmit","select","autoComplete","MIN_PASSWORD_LENGTH"],"mappings":"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","file":"2.288df6d9116cbb78911e.js","sourcesContent":["import { ApiMessage } from '../../../api/types';\nimport { MediaViewerOrigin } from '../../../types';\n\nimport { ANIMATION_END_DELAY } from '../../../config';\nimport { getMessageContent, getPhotoFullDimensions, getVideoDimensions } from '../../../modules/helpers';\nimport {\n AVATAR_FULL_DIMENSIONS,\n calculateDimensions,\n getMediaViewerAvailableDimensions,\n MEDIA_VIEWER_MEDIA_QUERY,\n REM,\n} from '../../common/helpers/mediaDimensions';\n\nimport windowSize from '../../../util/windowSize';\n\nconst ANIMATION_DURATION = 200;\n\nexport function animateOpening(\n hasFooter: boolean, origin: MediaViewerOrigin, bestImageData: string, message?: ApiMessage,\n) {\n const { mediaEl: fromImage } = getNodes(origin, message);\n if (!fromImage) {\n return;\n }\n\n const { width: windowWidth } = windowSize.get();\n\n let isVideo = false;\n let mediaSize;\n if (message) {\n const { photo, video, webPage } = getMessageContent(message);\n isVideo = Boolean(video);\n mediaSize = video ? getVideoDimensions(video)! : getPhotoFullDimensions((photo || webPage!.photo)!)!;\n } else {\n mediaSize = AVATAR_FULL_DIMENSIONS;\n }\n\n // eslint-disable-next-line max-len\n const {\n width: availableWidth, height: availableHeight,\n } = getMediaViewerAvailableDimensions(hasFooter, isVideo);\n const { width: toWidth, height: toHeight } = calculateDimensions(\n availableWidth, availableHeight, mediaSize.width, mediaSize.height,\n );\n const toLeft = (windowWidth - toWidth) / 2;\n const toTop = getTopOffset(hasFooter) + (availableHeight - toHeight) / 2;\n\n let {\n top: fromTop, left: fromLeft, width: fromWidth, height: fromHeight,\n } = fromImage.getBoundingClientRect();\n\n if ([\n MediaViewerOrigin.SharedMedia,\n MediaViewerOrigin.Album,\n MediaViewerOrigin.ScheduledAlbum,\n MediaViewerOrigin.SearchResult,\n ].includes(origin)) {\n const uncovered = uncover(toWidth, toHeight, fromTop, fromLeft, fromWidth, fromHeight);\n fromTop = uncovered.top;\n fromLeft = uncovered.left;\n fromWidth = uncovered.width;\n fromHeight = uncovered.height;\n }\n\n const fromTranslateX = (fromLeft + fromWidth / 2) - (toLeft + toWidth / 2);\n const fromTranslateY = (fromTop + fromHeight / 2) - (toTop + toHeight / 2);\n const fromScaleX = fromWidth / toWidth;\n const fromScaleY = fromHeight / toHeight;\n\n const ghost = createGhost(bestImageData || fromImage);\n applyStyles(ghost, {\n top: `${toTop}px`,\n left: `${toLeft}px`,\n width: `${toWidth}px`,\n height: `${toHeight}px`,\n transform: `translate3d(${fromTranslateX}px, ${fromTranslateY}px, 0) scale(${fromScaleX}, ${fromScaleY})`,\n });\n applyShape(ghost, origin);\n\n document.body.classList.add('ghost-animating');\n\n requestAnimationFrame(() => {\n document.body.appendChild(ghost);\n\n requestAnimationFrame(() => {\n ghost.style.transform = '';\n clearShape(ghost);\n\n setTimeout(() => {\n requestAnimationFrame(() => {\n document.body.removeChild(ghost);\n document.body.classList.remove('ghost-animating');\n });\n }, ANIMATION_DURATION + ANIMATION_END_DELAY);\n });\n });\n}\n\nexport function animateClosing(origin: MediaViewerOrigin, bestImageData: string, message?: ApiMessage) {\n const { container, mediaEl: toImage } = getNodes(origin, message);\n if (!toImage) {\n return;\n }\n\n const fromImage = document.getElementById('MediaViewer')!.querySelector<HTMLImageElement>(\n '.active .media-viewer-content img, .active .media-viewer-content video',\n );\n if (!fromImage || !toImage) {\n return;\n }\n\n const {\n top: fromTop, left: fromLeft, width: fromWidth, height: fromHeight,\n } = fromImage.getBoundingClientRect();\n const {\n top: targetTop, left: toLeft, width: toWidth, height: toHeight,\n } = toImage.getBoundingClientRect();\n\n let toTop = targetTop;\n if (!isElementInViewport(container)) {\n const { height: windowHeight } = windowSize.get();\n toTop = targetTop < fromTop ? -toHeight : windowHeight;\n }\n\n const fromTranslateX = (fromLeft + fromWidth / 2) - (toLeft + toWidth / 2);\n const fromTranslateY = (fromTop + fromHeight / 2) - (toTop + toHeight / 2);\n let fromScaleX = fromWidth / toWidth;\n let fromScaleY = fromHeight / toHeight;\n\n const shouldFadeOut = (\n [MediaViewerOrigin.Inline, MediaViewerOrigin.ScheduledInline].includes(origin)\n && !isMessageImageFullyVisible(container, toImage)\n ) || (\n [MediaViewerOrigin.Album, MediaViewerOrigin.ScheduledAlbum].includes(origin)\n && !isMessageImageFullyVisible(container, toImage)\n );\n\n if ([\n MediaViewerOrigin.SharedMedia,\n MediaViewerOrigin.Album,\n MediaViewerOrigin.ScheduledAlbum,\n MediaViewerOrigin.SearchResult,\n ].includes(origin)) {\n if (fromScaleX > fromScaleY) {\n fromScaleX = fromScaleY;\n } else if (fromScaleY > fromScaleX) {\n fromScaleY = fromScaleX;\n }\n }\n\n const ghost = createGhost(bestImageData || toImage);\n applyStyles(ghost, {\n top: `${toTop}px`,\n left: `${toLeft}px`,\n width: `${toWidth}px`,\n height: `${toHeight}px`,\n transform: `translate3d(${fromTranslateX}px, ${fromTranslateY}px, 0) scale(${fromScaleX}, ${fromScaleY})`,\n });\n\n requestAnimationFrame(() => {\n document.body.classList.add('ghost-animating');\n document.body.appendChild(ghost);\n\n requestAnimationFrame(() => {\n ghost.style.transform = '';\n if (shouldFadeOut) {\n ghost.style.opacity = '0';\n }\n\n applyShape(ghost, origin);\n\n setTimeout(() => {\n requestAnimationFrame(() => {\n document.body.removeChild(ghost);\n document.body.classList.remove('ghost-animating');\n });\n }, ANIMATION_DURATION + ANIMATION_END_DELAY);\n });\n });\n}\n\nfunction createGhost(source: string | HTMLImageElement | HTMLVideoElement) {\n const ghost = document.createElement('div');\n ghost.classList.add('ghost');\n\n const img = new Image();\n\n if (typeof source === 'string') {\n img.src = source;\n } else if (source instanceof HTMLVideoElement) {\n img.src = source.poster;\n } else {\n img.src = source.src;\n }\n\n ghost.appendChild(img);\n\n return ghost;\n}\n\nfunction uncover(realWidth: number, realHeight: number, top: number, left: number, width: number, height: number) {\n if (realWidth === realHeight) {\n const size = Math.max(width, height) * (realWidth / realHeight);\n left -= (size - width) / 2;\n top -= (size - height) / 2;\n width = size;\n height = size;\n } else if (realWidth > realHeight) {\n const srcWidth = width;\n width = height * (realWidth / realHeight);\n left -= (width - srcWidth) / 2;\n } else if (realHeight > realWidth) {\n const srcHeight = height;\n height = width * (realHeight / realWidth);\n top -= (height - srcHeight) / 2;\n }\n\n return {\n top, left, width, height,\n };\n}\n\nfunction isElementInViewport(el: HTMLElement) {\n if (el.style.display === 'none') {\n return false;\n }\n\n const rect = el.getBoundingClientRect();\n const { height: windowHeight } = windowSize.get();\n\n return (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);\n}\n\nfunction isMessageImageFullyVisible(container: HTMLElement, imageEl: HTMLElement) {\n const messageListElement = document.querySelector<HTMLDivElement>('.active > .MessageList')!;\n let imgOffsetTop = container.offsetTop + imageEl.closest<HTMLDivElement>('.content-inner, .WebPage')!.offsetTop;\n if (container.id.includes('album-media-')) {\n imgOffsetTop += container.parentElement!.offsetTop + container.closest<HTMLDivElement>('.Message')!.offsetTop;\n }\n\n return imgOffsetTop > messageListElement.scrollTop\n && imgOffsetTop + imageEl.offsetHeight < messageListElement.scrollTop + messageListElement.offsetHeight;\n}\n\nfunction getTopOffset(hasFooter: boolean) {\n const mql = window.matchMedia(MEDIA_VIEWER_MEDIA_QUERY);\n let topOffsetRem = 4.125;\n if (hasFooter) {\n topOffsetRem += mql.matches ? 0.875 : 3.375;\n }\n\n return topOffsetRem * REM;\n}\n\nfunction applyStyles(element: HTMLElement, styles: Record<string, string>) {\n Object.assign(element.style, styles);\n}\n\nfunction getNodes(origin: MediaViewerOrigin, message?: ApiMessage) {\n let containerSelector;\n let mediaSelector;\n\n switch (origin) {\n case MediaViewerOrigin.Album:\n case MediaViewerOrigin.ScheduledAlbum:\n containerSelector = `.active > .MessageList #album-media-${message!.id}`;\n mediaSelector = '.full-media';\n break;\n\n case MediaViewerOrigin.SharedMedia:\n containerSelector = `#shared-media${message!.id}`;\n mediaSelector = 'img';\n break;\n\n case MediaViewerOrigin.SearchResult:\n containerSelector = `#search-media${message!.id}`;\n mediaSelector = 'img';\n break;\n\n case MediaViewerOrigin.MiddleHeaderAvatar:\n containerSelector = '.MiddleHeader .ChatInfo .Avatar';\n mediaSelector = 'img.avatar-media';\n break;\n\n case MediaViewerOrigin.ProfileAvatar:\n containerSelector = '#RightColumn .active .profile-info .Avatar';\n mediaSelector = 'img.avatar-media';\n break;\n\n case MediaViewerOrigin.ScheduledInline:\n case MediaViewerOrigin.Inline:\n default:\n containerSelector = `.active > .MessageList #message${message!.id}`;\n mediaSelector = '.message-content .full-media, .message-content .thumbnail';\n }\n\n const container = document.querySelector<HTMLElement>(containerSelector)!;\n const mediaEls = container && container.querySelectorAll<HTMLImageElement | HTMLVideoElement>(mediaSelector);\n\n return {\n container,\n mediaEl: mediaEls && mediaEls[mediaEls.length - 1],\n };\n}\n\nfunction applyShape(ghost: HTMLDivElement, origin: MediaViewerOrigin) {\n switch (origin) {\n case MediaViewerOrigin.Album:\n case MediaViewerOrigin.ScheduledAlbum:\n case MediaViewerOrigin.Inline:\n case MediaViewerOrigin.ScheduledInline:\n ghost.classList.add('rounded-corners');\n break;\n\n case MediaViewerOrigin.SharedMedia:\n case MediaViewerOrigin.SearchResult:\n (ghost.firstChild as HTMLElement).style.objectFit = 'cover';\n break;\n\n case MediaViewerOrigin.MiddleHeaderAvatar:\n case MediaViewerOrigin.ProfileAvatar:\n ghost.classList.add('circle');\n break;\n }\n}\n\nfunction clearShape(ghost: HTMLDivElement) {\n (ghost.firstChild as HTMLElement).style.objectFit = 'default';\n ghost.classList.remove('rounded-corners', 'circle');\n}\n","import React, { FC, useCallback } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiChat, ApiMessage, ApiUser } from '../../api/types';\n\nimport { getSenderTitle, isChatPrivate } from '../../modules/helpers';\nimport { formatMediaDateTime } from '../../util/dateFormat';\nimport renderText from '../common/helpers/renderText';\nimport {\n selectChat,\n selectChatMessage,\n selectSender,\n selectUser,\n} from '../../modules/selectors';\nimport { pick } from '../../util/iteratees';\nimport useLang from '../../hooks/useLang';\n\nimport Avatar from '../common/Avatar';\n\nimport './SenderInfo.scss';\n\ntype OwnProps = {\n chatId?: number;\n messageId?: number;\n isAvatar?: boolean;\n};\n\ntype StateProps = {\n sender?: ApiUser | ApiChat;\n message?: ApiMessage;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'closeMediaViewer' | 'focusMessage'>;\n\nconst SenderInfo: FC<OwnProps & StateProps & DispatchProps> = ({\n chatId, messageId, sender, isAvatar, message, closeMediaViewer, focusMessage,\n}) => {\n const handleFocusMessage = useCallback(() => {\n closeMediaViewer();\n focusMessage({ chatId, messageId });\n }, [chatId, focusMessage, messageId, closeMediaViewer]);\n\n useLang();\n\n if (!sender || (!message && !isAvatar)) {\n return undefined;\n }\n\n const isFromChat = sender.id < 0;\n const senderTitle = getSenderTitle(sender);\n\n return (\n <div className=\"SenderInfo\" onClick={handleFocusMessage}>\n {isFromChat ? (\n <Avatar key={sender.id} size=\"medium\" chat={sender as ApiChat} />\n ) : (\n <Avatar key={sender.id} size=\"medium\" user={sender as ApiUser} />\n )}\n <div className=\"meta\">\n <div className=\"title\">\n {senderTitle && renderText(senderTitle)}\n </div>\n <div className=\"date\">\n {isAvatar ? 'Profile photo' : formatMediaDateTime(message!.date * 1000)}\n </div>\n </div>\n </div>\n );\n};\n\nexport default withGlobal<OwnProps>(\n (global, { chatId, messageId, isAvatar }): StateProps => {\n if (isAvatar && chatId) {\n return {\n sender: isChatPrivate(chatId) ? selectUser(global, chatId) : selectChat(global, chatId),\n };\n }\n\n if (!messageId || !chatId) {\n return {};\n }\n\n const message = selectChatMessage(global, chatId, messageId);\n\n return {\n message,\n sender: message && selectSender(global, message),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['closeMediaViewer', 'focusMessage']),\n)(SenderInfo);\n","import React, {\n FC, useCallback, useEffect, useMemo, useState,\n} from '../../lib/teact/teact';\n\nimport { ApiMessage } from '../../api/types';\n\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport download from '../../util/download';\nimport { getMessageMediaHash } from '../../modules/helpers';\nimport useMediaWithDownloadProgress from '../../hooks/useMediaWithDownloadProgress';\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\nimport DropdownMenu from '../ui/DropdownMenu';\nimport MenuItem from '../ui/MenuItem';\nimport ProgressSpinner from '../ui/ProgressSpinner';\n\nimport './MediaViewerActions.scss';\n\ntype OwnProps = {\n mediaData?: string;\n isVideo: boolean;\n isZoomed: boolean;\n message?: ApiMessage;\n fileName?: string;\n isAvatar?: boolean;\n onCloseMediaViewer: NoneToVoidFunction;\n onForward: NoneToVoidFunction;\n onZoomToggle: NoneToVoidFunction;\n};\n\nconst MediaViewerActions: FC<OwnProps> = ({\n mediaData,\n isVideo,\n isZoomed,\n message,\n fileName,\n isAvatar,\n onCloseMediaViewer,\n onForward,\n onZoomToggle,\n}) => {\n const [isVideoDownloadAllowed, setIsVideoDownloadAllowed] = useState(false);\n const videoMediaHash = isVideo && message ? getMessageMediaHash(message, 'download') : undefined;\n const {\n mediaData: videoBlobUrl, downloadProgress,\n } = useMediaWithDownloadProgress(videoMediaHash, !isVideoDownloadAllowed);\n\n // Download with browser when fully loaded\n useEffect(() => {\n if (isVideoDownloadAllowed && videoBlobUrl) {\n download(videoBlobUrl, fileName!);\n setIsVideoDownloadAllowed(false);\n }\n }, [fileName, videoBlobUrl, isVideoDownloadAllowed]);\n\n // Cancel download on slide change\n useEffect(() => {\n setIsVideoDownloadAllowed(false);\n }, [videoMediaHash]);\n\n const handleVideoDownloadClick = useCallback((e: React.SyntheticEvent<HTMLElement>) => {\n e.stopPropagation();\n setIsVideoDownloadAllowed((isAllowed) => !isAllowed);\n }, []);\n\n const lang = useLang();\n\n const MenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {\n return ({ onTrigger, isOpen }) => (\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n className={isOpen ? 'active' : undefined}\n onClick={onTrigger}\n ariaLabel=\"More actions\"\n >\n <i className=\"icon-more\" />\n </Button>\n );\n }, []);\n\n if (IS_MOBILE_SCREEN) {\n return (\n <div className=\"MediaViewerActions-mobile\">\n <DropdownMenu\n trigger={MenuButton}\n positionX=\"right\"\n >\n {!isAvatar && (\n <MenuItem\n icon=\"forward\"\n onClick={onForward}\n >\n {lang('Forward')}\n </MenuItem>\n )}\n {isVideo ? (\n <MenuItem\n icon={isVideoDownloadAllowed ? 'close' : 'download'}\n onClick={handleVideoDownloadClick}\n >\n {isVideoDownloadAllowed ? `${Math.round(downloadProgress * 100)}% Downloading...` : 'Download'}\n </MenuItem>\n ) : (\n <MenuItem\n icon=\"download\"\n href={mediaData}\n download={fileName}\n >\n {lang('AccActionDownload')}\n </MenuItem>\n )}\n </DropdownMenu>\n {isVideoDownloadAllowed && <ProgressSpinner progress={downloadProgress} size=\"s\" noCross />}\n </div>\n );\n }\n\n return (\n <div className=\"MediaViewerActions\">\n {!isAvatar && (\n <>\n <Button\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={lang('Forward')}\n onClick={onForward}\n >\n <i className=\"icon-forward\" />\n </Button>\n </>\n )}\n {isVideo ? (\n <Button\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={lang('AccActionDownload')}\n onClick={handleVideoDownloadClick}\n >\n {isVideoDownloadAllowed ? (\n <ProgressSpinner progress={downloadProgress} size=\"s\" onClick={handleVideoDownloadClick} />\n ) : (\n <i className=\"icon-download\" />\n )}\n </Button>\n ) : (\n <Button\n href={mediaData}\n download={fileName}\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={lang('AccActionDownload')}\n >\n <i className=\"icon-download\" />\n </Button>\n )}\n <Button\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={isZoomed ? 'Zoom Out' : 'Zoom In'}\n onClick={onZoomToggle}\n >\n <i className={isZoomed ? 'icon-zoom-out' : 'icon-zoom-in'} />\n </Button>\n <Button\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={lang('Close')}\n onClick={onCloseMediaViewer}\n >\n <i className=\"icon-close\" />\n </Button>\n </div>\n );\n};\n\nexport default MediaViewerActions;\n","import React, { FC, useEffect, useState } from '../../lib/teact/teact';\nimport { throttle } from '../../util/schedulers';\nimport { TextPart } from '../common/helpers/renderMessageText';\nimport { REM } from '../common/helpers/mediaDimensions';\n\nimport './MediaViewerFooter.scss';\n\nconst RESIZE_THROTTLE_MS = 500;\n\ntype OwnProps = {\n text: TextPart | TextPart[];\n onClick: () => void;\n isHideable: boolean;\n};\n\nconst MediaViewerFooter: FC<OwnProps> = ({ text = '', isHideable, onClick }) => {\n const [isMultiline, setIsMultiline] = useState(false);\n useEffect(() => {\n const footerContent = document.querySelector('.MediaViewerFooter .media-text') as HTMLDivElement | null;\n\n const checkIsMultiline = () => {\n const height = footerContent ? footerContent.clientHeight : 0;\n\n setIsMultiline(height > REM * 2);\n };\n\n // First run for initial detection of multiline footer text\n checkIsMultiline();\n\n const handleResize = throttle(checkIsMultiline, RESIZE_THROTTLE_MS, true);\n\n window.addEventListener('resize', handleResize, false);\n\n return () => {\n window.removeEventListener('resize', handleResize, false);\n };\n }, []);\n\n function stopEvent(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {\n if (text) {\n e.stopPropagation();\n }\n }\n\n return (\n <div className={`MediaViewerFooter ${isHideable ? 'hideable' : ''}`} onClick={stopEvent}>\n {text && (\n <div className=\"media-viewer-footer-content\" onClick={onClick}>\n <p className={`media-text custom-scroll ${isMultiline ? 'multiline' : ''}`}>{text}</p>\n </div>\n )}\n </div>\n );\n};\n\nexport default MediaViewerFooter;\n","import { useLayoutEffect, useState } from '../lib/teact/teact';\nimport { PLATFORM_ENV } from '../util/environment';\n\ntype RefType = {\n current: HTMLElement | null;\n};\n\ntype ReturnType = [boolean, () => void, () => void] | [false];\ntype CallbackType = (isPlayed: boolean) => void;\n\nconst prop = getBrowserFullscreenElementProp();\n\nexport default function useFullscreenStatus(elRef: RefType, setIsPlayed: CallbackType): ReturnType {\n const [isFullscreen, setIsFullscreen] = useState(Boolean(prop && document[prop]));\n\n const setFullscreen = () => {\n if (!elRef.current || !(prop || PLATFORM_ENV === 'iOS')) {\n return;\n }\n\n if (elRef.current.requestFullscreen) {\n elRef.current.requestFullscreen();\n } else if (elRef.current.webkitRequestFullscreen) {\n elRef.current.webkitRequestFullscreen();\n } else if (elRef.current.webkitEnterFullscreen) {\n elRef.current.webkitEnterFullscreen();\n } else if (elRef.current.mozRequestFullScreen) {\n elRef.current.mozRequestFullScreen();\n }\n\n setIsFullscreen(true);\n };\n\n const exitFullscreen = () => {\n if (!elRef.current) {\n return;\n }\n\n if (document.exitFullscreen) {\n document.exitFullscreen();\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen();\n } else if (document.webkitCancelFullScreen) {\n document.webkitCancelFullScreen();\n } else if (document.webkitExitFullscreen) {\n document.webkitExitFullscreen();\n }\n\n setIsFullscreen(false);\n };\n\n useLayoutEffect(() => {\n const listener = () => { setIsFullscreen(Boolean(prop && document[prop])); };\n const listenerEnter = () => { setIsFullscreen(true); };\n const listenerExit = () => {\n setIsFullscreen(false);\n setIsPlayed(false);\n };\n const video = elRef.current;\n\n document.addEventListener('fullscreenchange', listener, false);\n document.addEventListener('webkitfullscreenchange', listener, false);\n document.addEventListener('mozfullscreenchange', listener, false);\n\n if (video) {\n video.addEventListener('webkitbeginfullscreen', listenerEnter, false);\n video.addEventListener('webkitendfullscreen', listenerExit, false);\n }\n\n return () => {\n document.removeEventListener('fullscreenchange', listener, false);\n document.removeEventListener('webkitfullscreenchange', listener, false);\n document.removeEventListener('mozfullscreenchange', listener, false);\n if (video) {\n video.removeEventListener('webkitbeginfullscreen', listenerEnter, false);\n video.removeEventListener('webkitendfullscreen', listenerExit, false);\n }\n };\n // eslint-disable-next-line\n }, []);\n\n if (!prop && PLATFORM_ENV !== 'iOS') {\n return [false];\n }\n\n return [isFullscreen, setFullscreen, exitFullscreen];\n}\n\nfunction getBrowserFullscreenElementProp() {\n if (typeof document.fullscreenElement !== 'undefined') {\n return 'fullscreenElement';\n } else if (typeof document.mozFullScreenElement !== 'undefined') {\n return 'mozFullScreenElement';\n } else if (typeof document.webkitFullscreenElement !== 'undefined') {\n return 'webkitFullscreenElement';\n }\n\n return '';\n}\n","const units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'];\n\nexport default (bytes: number) => {\n const number = bytes === 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024));\n\n return `${(bytes / 1024 ** Math.floor(number)).toFixed(1)} ${units[number]}`;\n};\n","import React, { FC, useState, useEffect } from '../../lib/teact/teact';\n\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport { formatMediaDuration } from '../../util/dateFormat';\nimport formatFileSize from './helpers/formatFileSize';\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\n\nimport './VideoPlayerControls.scss';\n\ntype IProps = {\n bufferedProgress: number;\n currentTime: number;\n duration: number;\n fileSize: number;\n isForceVisible: boolean;\n isForceMobileVersion?: boolean;\n isPlayed: boolean;\n isFullscreenSupported: boolean;\n isFullscreen: boolean;\n onChangeFullscreen: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n onPlayPause: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n onSeek: OnChangeHandler;\n};\n\ntype OnChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => void;\n\nconst stopEvent = (e: React.MouseEvent<HTMLElement>) => {\n e.stopPropagation();\n};\n\nconst HIDE_CONTROLS_TIMEOUT_MS = 800;\n\nconst VideoPlayerControls: FC<IProps> = ({\n bufferedProgress,\n currentTime,\n duration,\n fileSize,\n isForceVisible,\n isForceMobileVersion,\n isPlayed,\n isFullscreenSupported,\n isFullscreen,\n onChangeFullscreen,\n onPlayPause,\n onSeek,\n}) => {\n const [isVisible, setVisibility] = useState(true);\n\n useEffect(() => {\n if (isForceVisible) {\n setVisibility(isForceVisible);\n }\n }, [isForceVisible]);\n\n useEffect(() => {\n let timeout: number | undefined;\n\n if (!isForceVisible) {\n if (IS_MOBILE_SCREEN) {\n setVisibility(false);\n } else {\n timeout = window.setTimeout(() => {\n setVisibility(false);\n }, HIDE_CONTROLS_TIMEOUT_MS);\n }\n }\n\n return () => {\n if (timeout) {\n window.clearTimeout(timeout);\n }\n };\n }, [isForceVisible]);\n\n useEffect(() => {\n if (isVisible || isForceVisible) {\n document.body.classList.add('video-controls-visible');\n }\n\n return () => {\n document.body.classList.remove('video-controls-visible');\n };\n }, [isForceVisible, isVisible]);\n\n const lang = useLang();\n\n if (!isVisible && !isForceVisible) {\n return undefined;\n }\n\n return (\n <div className={`VideoPlayerControls ${isForceMobileVersion ? 'mobile' : ''}`} onClick={stopEvent}>\n {renderSeekLine(currentTime, duration, bufferedProgress, onSeek)}\n <Button\n ariaLabel={lang('AccActionPlay')}\n size=\"tiny\"\n ripple={!IS_MOBILE_SCREEN}\n color=\"translucent-white\"\n className=\"play\"\n onClick={onPlayPause}\n >\n <i className={isPlayed ? 'icon-pause' : 'icon-play'} />\n </Button>\n {renderTime(currentTime, duration)}\n {bufferedProgress < 1 && renderFileSize(bufferedProgress, fileSize)}\n {isFullscreenSupported && (\n <Button\n ariaLabel=\"Fullscreen\"\n size=\"tiny\"\n color=\"translucent-white\"\n className=\"fullscreen\"\n onClick={onChangeFullscreen}\n >\n <i className={`${isFullscreen ? 'icon-smallscreen' : 'icon-fullscreen'}`} />\n </Button>\n )}\n </div>\n );\n};\n\nfunction renderTime(currentTime: number, duration: number) {\n return (\n <div className=\"player-time\">\n {`${formatMediaDuration(currentTime)} / ${formatMediaDuration(duration)}`}\n </div>\n );\n}\n\nfunction renderFileSize(downloadedPercent: number, totalSize: number) {\n return (\n <div className=\"player-file-size\">\n {`${formatFileSize(totalSize * downloadedPercent)} / ${formatFileSize(totalSize)}`}\n </div>\n );\n}\n\nfunction renderSeekLine(currentTime: number, duration: number, bufferedProgress: number, onSeek: OnChangeHandler) {\n const percentagePlayed = (currentTime / duration) * 100;\n const percentageBuffered = bufferedProgress * 100;\n\n return (\n <div className=\"player-seekline\">\n <div className=\"player-seekline-track\">\n <div\n className=\"player-seekline-buffered\"\n // @ts-ignore teact feature\n style={`width: ${percentageBuffered || 0}%`}\n />\n <div\n className=\"player-seekline-played\"\n // @ts-ignore teact feature\n style={`width: ${percentagePlayed || 0}%`}\n />\n <input\n min=\"0\"\n max=\"100\"\n step={0.01}\n type=\"range\"\n onInput={onSeek}\n className=\"player-seekline-input\"\n value={percentagePlayed || 0}\n />\n </div>\n </div>\n );\n}\n\nexport default VideoPlayerControls;\n","import React, {\n FC, memo, useCallback, useEffect, useRef, useState,\n} from '../../lib/teact/teact';\n\nimport { IDimensions } from '../../modules/helpers';\n\nimport { IS_IOS, IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../util/environment';\nimport useShowTransition from '../../hooks/useShowTransition';\nimport useBuffering from '../../hooks/useBuffering';\nimport useFullscreenStatus from '../../hooks/useFullscreen';\nimport useVideoCleanup from '../../hooks/useVideoCleanup';\nimport safePlay from '../../util/safePlay';\n\nimport VideoPlayerControls from './VideoPlayerControls';\nimport ProgressSpinner from '../ui/ProgressSpinner';\n\nimport './VideoPlayer.scss';\n\ntype OwnProps = {\n url?: string;\n isGif?: boolean;\n posterData?: string;\n posterSize?: IDimensions;\n downloadProgress?: number;\n fileSize: number;\n isMediaViewerOpen?: boolean;\n noPlay?: boolean;\n onClose: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n};\n\nconst MOBILE_VERSION_CONTROL_WIDTH = 400;\n\nconst VideoPlayer: FC<OwnProps> = ({\n url,\n isGif,\n posterData,\n posterSize,\n downloadProgress,\n fileSize,\n isMediaViewerOpen,\n noPlay,\n onClose,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const videoRef = useRef<HTMLVideoElement>(null);\n const [isPlayed, setIsPlayed] = useState(!IS_TOUCH_ENV || !IS_IOS);\n const [currentTime, setCurrentTime] = useState(0);\n const [isControlsVisible, setIsControlsVisible] = useState(true);\n\n const [isFullscreen, setFullscreen, exitFullscreen] = useFullscreenStatus(videoRef, setIsPlayed);\n\n const { isBuffered, bufferedProgress, bufferingHandlers } = useBuffering();\n const {\n shouldRender: shouldRenderSpinner,\n transitionClassNames: spinnerClassNames,\n } = useShowTransition(!isBuffered, undefined, undefined, 'slow');\n\n useEffect(() => {\n if (noPlay || !isMediaViewerOpen) {\n videoRef.current!.pause();\n } else if (url && !IS_TOUCH_ENV) {\n // Chrome does not automatically start playing when `url` becomes available (even with `autoPlay`),\n // so we force it here. Contrary, iOS does not allow to call `play` without mouse event,\n // so we need to use `autoPlay` instead to allow pre-buffering.\n safePlay(videoRef.current!);\n }\n }, [noPlay, isMediaViewerOpen, url]);\n\n useEffect(() => {\n if (videoRef.current!.currentTime === videoRef.current!.duration) {\n setCurrentTime(0);\n setIsPlayed(false);\n } else {\n setCurrentTime(videoRef.current!.currentTime);\n }\n }, [currentTime]);\n\n const togglePlayState = useCallback((e: React.MouseEvent<HTMLElement, MouseEvent> | KeyboardEvent) => {\n e.stopPropagation();\n if (isPlayed) {\n videoRef.current!.pause();\n setIsPlayed(false);\n } else {\n videoRef.current!.play();\n setIsPlayed(true);\n }\n }, [isPlayed]);\n\n useVideoCleanup(videoRef, []);\n\n const handleMouseOver = useCallback(() => {\n setIsControlsVisible(true);\n }, []);\n\n const handleMouseOut = useCallback(() => {\n setIsControlsVisible(false);\n }, []);\n\n const handleTimeUpdate = useCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {\n setCurrentTime(e.currentTarget.currentTime);\n }, []);\n\n const handleEnded = useCallback(() => {\n setCurrentTime(0);\n setIsPlayed(false);\n }, []);\n\n const handleFullscreenChange = useCallback(() => {\n if (isFullscreen && exitFullscreen) {\n exitFullscreen();\n } else if (!isFullscreen && setFullscreen) {\n setFullscreen();\n }\n }, [exitFullscreen, isFullscreen, setFullscreen]);\n\n const handleSeek = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n\n videoRef.current!.currentTime = (Number(e.target.value) * videoRef.current!.duration) / 100;\n }, []);\n\n const toggleControls = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n setIsControlsVisible(!isControlsVisible);\n }, [isControlsVisible]);\n\n useEffect(() => {\n const togglePayingStateBySpace = (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n togglePlayState(e);\n }\n };\n\n document.addEventListener('keydown', togglePayingStateBySpace, false);\n\n return () => {\n document.removeEventListener('keydown', togglePayingStateBySpace, false);\n };\n }, [togglePlayState]);\n\n const wrapperStyle = posterSize && `width: ${posterSize.width}px; height: ${posterSize.height}px`;\n const videoStyle = `background-image: url(${posterData})`;\n\n return (\n <div\n className=\"VideoPlayer\"\n onClick={!isGif && IS_MOBILE_SCREEN ? toggleControls : undefined}\n onMouseOver={!isGif ? handleMouseOver : undefined}\n onMouseOut={!isGif ? handleMouseOut : undefined}\n >\n <div\n // @ts-ignore\n style={wrapperStyle}\n >\n {/* eslint-disable-next-line jsx-a11y/media-has-caption */}\n <video\n ref={videoRef}\n autoPlay={IS_TOUCH_ENV}\n playsInline\n loop={isGif}\n // This is to force auto playing on mobiles\n muted={isGif}\n id=\"media-viewer-video\"\n // @ts-ignore\n style={videoStyle}\n onEnded={handleEnded}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...bufferingHandlers}\n onTimeUpdate={handleTimeUpdate}\n >\n {url && <source src={url} />}\n </video>\n </div>\n {shouldRenderSpinner && (\n <div className={['spinner-container', spinnerClassNames].join(' ')}>\n {!isBuffered && <div className=\"buffering\">Buffering...</div>}\n <ProgressSpinner\n size=\"xl\"\n progress={isBuffered ? 1 : downloadProgress}\n square\n onClick={onClose}\n />\n </div>\n )}\n {!isGif && !shouldRenderSpinner && (\n <VideoPlayerControls\n isPlayed={isPlayed}\n bufferedProgress={bufferedProgress}\n currentTime={currentTime}\n isFullscreenSupported={Boolean(setFullscreen)}\n isFullscreen={isFullscreen}\n fileSize={fileSize}\n duration={videoRef.current ? videoRef.current.duration : 0}\n isForceVisible={!isPlayed || isControlsVisible}\n isForceMobileVersion={posterSize && posterSize.width < MOBILE_VERSION_CONTROL_WIDTH}\n onSeek={handleSeek}\n onChangeFullscreen={handleFullscreenChange}\n onPlayPause={togglePlayState}\n />\n )}\n </div>\n );\n};\n\nexport default memo(VideoPlayer);\n","import React, {\n FC, memo, useCallback, useEffect, useRef, useState,\n} from '../../lib/teact/teact';\n\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport buildClassName from '../../util/buildClassName';\nimport usePrevious from '../../hooks/usePrevious';\nimport useShowTransition from '../../hooks/useShowTransition';\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\n\nimport './ZoomControls.scss';\n\ntype OwnProps = {\n isShown: boolean;\n onChangeZoom: (level: number, canCloseZoom?: boolean) => void;\n};\n\nexport const MAX_ZOOM_LEVEL = 3;\nexport const MIN_ZOOM_LEVEL = 1;\nconst ONE_STEP_PERCENT = 100 / (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL);\nconst RESET_ZOOM_LEVEL = 1.5;\n\nconst ZoomControls: FC<OwnProps> = ({ isShown, onChangeZoom }) => {\n const { transitionClassNames } = useShowTransition(isShown);\n const prevIsShown = usePrevious<boolean>(isShown);\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n const [zoomLevel, setZoomLevel] = useState(1);\n const isSeeking = useRef<boolean>(false);\n\n useEffect(() => {\n if (isShown && !prevIsShown) {\n setZoomLevel(RESET_ZOOM_LEVEL);\n }\n }, [isShown, prevIsShown]);\n\n const handleZoomOut = () => {\n if (inputRef.current) {\n setZoomLevel(Math.max(MIN_ZOOM_LEVEL, zoomLevel - 0.5));\n }\n };\n\n const handleZoomIn = () => {\n if (inputRef.current) {\n setZoomLevel(Math.min(MAX_ZOOM_LEVEL, zoomLevel + 0.5));\n }\n };\n\n const handleStartSeek = useCallback(() => {\n isSeeking.current = true;\n }, []);\n\n const handleStopSeek = useCallback(() => {\n isSeeking.current = false;\n if (zoomLevel === 1) {\n onChangeZoom(zoomLevel, !isSeeking.current);\n }\n }, [onChangeZoom, zoomLevel]);\n\n const handleSeeklineChange = (e:React.ChangeEvent<HTMLInputElement>) => {\n setZoomLevel(Math.min(MAX_ZOOM_LEVEL, Math.max(Number(e.target.value), MIN_ZOOM_LEVEL)));\n };\n\n useEffect(() => {\n onChangeZoom(zoomLevel, !isSeeking.current);\n }, [zoomLevel, onChangeZoom]);\n\n const lang = useLang();\n\n const className = buildClassName(\n 'ZoomControls',\n transitionClassNames,\n );\n\n return (\n <div className={className}>\n <Button\n disabled={zoomLevel === MIN_ZOOM_LEVEL}\n size=\"tiny\"\n color=\"translucent-white\"\n ariaLabel={lang('ZoomOut')}\n className=\"zoom-out\"\n ripple={!IS_MOBILE_SCREEN}\n onClick={handleZoomOut}\n >\n <i className=\"icon-zoom-out\" />\n </Button>\n <Button\n disabled={zoomLevel === MAX_ZOOM_LEVEL}\n size=\"tiny\"\n color=\"translucent-white\"\n ariaLabel=\"Zoom In\"\n className=\"zoom-in\"\n ripple={!IS_MOBILE_SCREEN}\n onClick={handleZoomIn}\n >\n <i className=\"icon-zoom-in\" />\n </Button>\n <div className=\"seekline\">\n <div className=\"seekline-track\">\n <div\n className=\"seekline-played\"\n // @ts-ignore teact feature\n style={`width: ${(zoomLevel - 1) * ONE_STEP_PERCENT}%`}\n />\n <input\n ref={inputRef}\n min={MIN_ZOOM_LEVEL}\n max={MAX_ZOOM_LEVEL}\n step=\"0.5\"\n value={zoomLevel}\n type=\"range\"\n className=\"seekline-input\"\n onChange={handleSeeklineChange}\n onMouseDown={handleStartSeek}\n onMouseUp={handleStopSeek}\n />\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(ZoomControls);\n","/*\n @source https://github.com/ajainarayanan/react-pan-zoom\n\n Heavily inspired/lifted from this idea: https://stackoverflow.com/a/39311435/661768\n without jqueryUI or jquery dependency.\n*/\nimport React, {\n FC, memo, useEffect, useRef, useState,\n} from '../../lib/teact/teact';\n\nimport { areSortedArraysEqual } from '../../util/iteratees';\n\nimport './PanZoom.scss';\n\nexport interface IDragData {\n x: number;\n y: number;\n dx: number;\n dy: number;\n}\n\nexport interface OwnProps {\n children: any;\n className?: string;\n noWrap: boolean;\n canPan: boolean;\n zoomLevel: number;\n panDeltaX: number;\n panDeltaY: number;\n onPan?: (x: number, y: number) => void;\n}\n\nconst INITIAL_MATRIX = [\n 1, 0, 0, 1, 0, 0,\n];\n\nconst SCALE_VALUES = {\n 1: 1,\n 1.5: 1.5,\n 2: 2.2,\n 2.5: 3.3,\n 3: 5.5,\n};\n\nconst ZOOM_SAFE_AREA = 150;\n\nfunction calculateSafeZoneOnZoom(oldScale: number, matrixData: number[], wrapper: HTMLDivElement | null) {\n const image = wrapper && wrapper.querySelector('.active img');\n if (!wrapper || !image) {\n return matrixData;\n }\n const wrapperRect = wrapper.getBoundingClientRect();\n const imageRect = image.getBoundingClientRect();\n\n const newImgWidth = (imageRect.width / oldScale) * matrixData[0];\n const newImgHeight = (imageRect.height / oldScale) * matrixData[3];\n const newImgX = (wrapperRect.width - newImgWidth) / 2 + matrixData[4];\n const newImgY = (wrapperRect.height - newImgHeight) / 2 + matrixData[5];\n if (wrapperRect.width && wrapperRect.width - ZOOM_SAFE_AREA < newImgX) {\n matrixData[4] -= newImgX + wrapperRect.width - ZOOM_SAFE_AREA;\n } else if (newImgWidth && newImgWidth + newImgX < ZOOM_SAFE_AREA) {\n matrixData[4] -= newImgWidth + newImgX - ZOOM_SAFE_AREA;\n }\n if (wrapperRect.height && wrapperRect.height - ZOOM_SAFE_AREA < newImgY) {\n matrixData[5] -= newImgY + wrapperRect.height - ZOOM_SAFE_AREA;\n } else if (newImgHeight && newImgHeight + newImgY < ZOOM_SAFE_AREA) {\n matrixData[5] -= newImgHeight + newImgY - ZOOM_SAFE_AREA;\n }\n\n return matrixData;\n}\n\nconst PanZoom: FC<OwnProps> = ({\n children,\n className,\n noWrap,\n canPan,\n zoomLevel,\n panDeltaX,\n panDeltaY,\n onPan,\n}) => {\n const tunedZoomLevel = SCALE_VALUES[zoomLevel as keyof typeof SCALE_VALUES] || zoomLevel;\n const [isDragging, setIsDragging] = useState<boolean>(false);\n const [dragData, setDragData] = useState<IDragData>({\n dx: panDeltaX, dy: panDeltaY, x: 0, y: 0,\n });\n // [zoom, skew, skew, zoom, dx, dy] - see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix()\n const [matrixData, setMatrixData] = useState<number[]>(INITIAL_MATRIX);\n // Used to set cursor while moving.\n // eslint-disable-next-line no-null/no-null\n const panWrapperRef = useRef<HTMLDivElement>(null);\n // Used to set transform for pan.\n // eslint-disable-next-line no-null/no-null\n const panContainerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const newZoomLevel = tunedZoomLevel || matrixData[0];\n const newPandx = panDeltaX || matrixData[4];\n const newPandy = panDeltaY || matrixData[5];\n\n const newMatrixData = [...matrixData];\n if (matrixData[0] !== newZoomLevel) {\n newMatrixData[0] = newZoomLevel || newMatrixData[0];\n newMatrixData[3] = newZoomLevel || newMatrixData[3];\n }\n if (matrixData[4] !== newPandx) {\n newMatrixData[4] = newPandx;\n }\n if (matrixData[5] !== newPandy) {\n newMatrixData[5] = newPandy;\n }\n\n if (!areSortedArraysEqual(matrixData, newMatrixData)) {\n setMatrixData(calculateSafeZoneOnZoom(matrixData[0], newMatrixData, panWrapperRef.current));\n }\n // eslint-disable-next-line\n }, [panDeltaX, panDeltaY, tunedZoomLevel]);\n\n useEffect(() => {\n if (!canPan) {\n setMatrixData(INITIAL_MATRIX);\n }\n }, [canPan]);\n\n useEffect(() => {\n if (panContainerRef.current) {\n panContainerRef.current.style.transform = `matrix(${matrixData.toString()})`;\n }\n }, [noWrap, matrixData]);\n\n const handleMouseDown = (e: React.MouseEvent<EventTarget>) => {\n if (!canPan) {\n return;\n }\n\n e.stopPropagation();\n e.preventDefault();\n\n const offsetX = matrixData[4];\n const offsetY = matrixData[5];\n const newDragData: IDragData = {\n dx: offsetX,\n dy: offsetY,\n x: e.pageX,\n y: e.pageY,\n };\n setDragData(newDragData);\n setIsDragging(true);\n\n if (panWrapperRef.current) {\n panWrapperRef.current.classList.add('move');\n }\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n\n if (panWrapperRef.current) {\n panWrapperRef.current.classList.remove('move');\n }\n\n if (onPan) {\n onPan(matrixData[4], matrixData[5]);\n }\n };\n\n function getNewMatrixData(x: number, y: number): number[] {\n const newMatrixData = [...matrixData];\n const deltaX = dragData.x - x;\n const deltaY = dragData.y - y;\n newMatrixData[4] = dragData.dx - deltaX;\n newMatrixData[5] = dragData.dy - deltaY;\n\n return newMatrixData;\n }\n\n const handleMouseMove = (e: React.MouseEvent<EventTarget>) => {\n if (isDragging) {\n const newMatrixData = getNewMatrixData(e.pageX, e.pageY);\n setMatrixData(newMatrixData);\n\n if (panContainerRef.current) {\n panContainerRef.current.style.transform = `matrix(${matrixData.toString()})`;\n }\n }\n };\n\n if (noWrap) {\n return children;\n }\n\n return (\n <div\n ref={panWrapperRef}\n className={`pan-wrapper ${className || ''}`}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseMove={handleMouseMove}\n >\n <div\n ref={panContainerRef}\n className=\"pan-container\"\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default memo(PanZoom);\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useRef, useState,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport {\n ApiChat, ApiMediaFormat, ApiMessage, ApiUser,\n} from '../../api/types';\nimport { MediaViewerOrigin } from '../../types';\n\nimport { ANIMATION_END_DELAY } from '../../config';\nimport { IS_IOS, IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../util/environment';\nimport {\n AVATAR_FULL_DIMENSIONS,\n MEDIA_VIEWER_MEDIA_QUERY,\n calculateMediaViewerDimensions,\n} from '../common/helpers/mediaDimensions';\nimport {\n selectChat,\n selectChatMessage,\n selectChatMessages,\n selectCurrentMediaSearch,\n selectListedIds,\n selectOutlyingIds,\n selectScheduledMessage,\n selectScheduledMessages,\n selectUser,\n} from '../../modules/selectors';\nimport {\n getChatAvatarHash,\n getChatMediaMessageIds,\n getMessageMediaFilename,\n getMessageMediaFormat,\n getMessageMediaHash,\n getMessageMediaThumbDataUri,\n getMessagePhoto,\n getMessageVideo,\n getMessageWebPagePhoto,\n getPhotoFullDimensions,\n getVideoDimensions,\n IDimensions,\n} from '../../modules/helpers';\nimport { pick } from '../../util/iteratees';\nimport { captureEvents, SwipeDirection } from '../../util/captureEvents';\nimport captureEscKeyListener from '../../util/captureEscKeyListener';\nimport { stopCurrentAudio } from '../../util/audioPlayer';\nimport useForceUpdate from '../../hooks/useForceUpdate';\nimport useMedia from '../../hooks/useMedia';\nimport useMediaWithDownloadProgress from '../../hooks/useMediaWithDownloadProgress';\nimport useBlurSync from '../../hooks/useBlurSync';\nimport usePrevious from '../../hooks/usePrevious';\nimport { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';\nimport { renderMessageText } from '../common/helpers/renderMessageText';\nimport { animateClosing, animateOpening } from './helpers/ghostAnimation';\nimport useLang from '../../hooks/useLang';\n\nimport Spinner from '../ui/Spinner';\nimport ShowTransition from '../ui/ShowTransition';\nimport Transition from '../ui/Transition';\nimport Button from '../ui/Button';\nimport SenderInfo from './SenderInfo';\nimport MediaViewerActions from './MediaViewerActions';\nimport MediaViewerFooter from './MediaViewerFooter';\nimport VideoPlayer from './VideoPlayer';\nimport ZoomControls from './ZoomControls';\nimport PanZoom from './PanZoom';\n\nimport './MediaViewer.scss';\n\ntype StateProps = {\n chatId?: number;\n threadId?: number;\n messageId?: number;\n senderId?: number;\n origin?: MediaViewerOrigin;\n avatarOwner?: ApiChat | ApiUser;\n message?: ApiMessage;\n chatMessages?: Record<number, ApiMessage>;\n collectionIds?: number[];\n animationLevel: 0 | 1 | 2;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'openMediaViewer' | 'closeMediaViewer' | 'openForwardMenu' | 'focusMessage'>;\n\nconst ANIMATION_DURATION = 350;\n\nconst MediaViewer: FC<StateProps & DispatchProps> = ({\n chatId,\n threadId,\n messageId,\n senderId,\n origin,\n avatarOwner,\n message,\n chatMessages,\n collectionIds,\n openMediaViewer,\n closeMediaViewer,\n openForwardMenu,\n focusMessage,\n animationLevel,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const animationKey = useRef<number>(null);\n const isOpen = Boolean(avatarOwner || messageId);\n const webPagePhoto = message ? getMessageWebPagePhoto(message) : undefined;\n const photo = message ? getMessagePhoto(message) : undefined;\n const video = message ? getMessageVideo(message) : undefined;\n const isWebPagePhoto = Boolean(webPagePhoto);\n const isPhoto = Boolean(photo || webPagePhoto);\n const isVideo = Boolean(video);\n const isGif = video ? video.isGif : undefined;\n const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;\n const isFromSearch = origin === MediaViewerOrigin.SearchResult;\n const slideAnimation = animationLevel >= 1 ? 'mv-slide' : 'none';\n const headerAnimation = animationLevel === 2 ? 'slide-fade' : 'none';\n const isGhostAnimation = animationLevel === 2;\n const fileName = avatarOwner ? `avatar${avatarOwner.id}.jpg` : message && getMessageMediaFilename(message);\n const prevSenderId = usePrevious<number | undefined>(senderId);\n const [canPanZoomWrap, setCanPanZoomWrap] = useState(false);\n const [isZoomed, setIsZoomed] = useState<boolean>(false);\n const [zoomLevel, setZoomLevel] = useState<number>(1);\n const [panDelta, setPanDelta] = useState({ x: 0, y: 0 });\n\n const messageIds = useMemo(() => {\n return isWebPagePhoto && messageId\n ? [messageId]\n : getChatMediaMessageIds(chatMessages || {}, collectionIds || [], isFromSharedMedia);\n }, [isWebPagePhoto, messageId, chatMessages, collectionIds, isFromSharedMedia]);\n\n const selectedMediaMessageIndex = messageId ? messageIds.indexOf(messageId) : -1;\n const isFirst = selectedMediaMessageIndex === 0 || selectedMediaMessageIndex === -1;\n const isLast = selectedMediaMessageIndex === messageIds.length - 1 || selectedMediaMessageIndex === -1;\n if (isOpen && (!prevSenderId || prevSenderId !== senderId || !animationKey.current)) {\n animationKey.current = selectedMediaMessageIndex;\n }\n\n function getMediaHash(full?: boolean) {\n if (avatarOwner) {\n return getChatAvatarHash(avatarOwner, full ? 'big' : 'normal');\n }\n\n return message && getMessageMediaHash(message, full ? 'viewerFull' : 'viewerPreview');\n }\n\n const blobUrlPictogram = useMedia(\n message && (isFromSharedMedia || isFromSearch) && getMessageMediaHash(message, 'pictogram'),\n undefined,\n ApiMediaFormat.BlobUrl,\n undefined,\n isGhostAnimation && ANIMATION_DURATION,\n );\n const blobUrlPreview = useMedia(\n getMediaHash(),\n undefined,\n avatarOwner ? ApiMediaFormat.DataUri : ApiMediaFormat.BlobUrl,\n undefined,\n isGhostAnimation && ANIMATION_DURATION,\n );\n const { mediaData: fullMediaData, downloadProgress } = useMediaWithDownloadProgress(\n getMediaHash(true),\n undefined,\n message && getMessageMediaFormat(message, 'viewerFull'),\n undefined,\n isGhostAnimation && ANIMATION_DURATION,\n );\n\n const localBlobUrl = (photo || video) ? (photo || video)!.blobUrl : undefined;\n let bestImageData = (!isVideo && (localBlobUrl || fullMediaData)) || blobUrlPreview || blobUrlPictogram;\n const thumbDataUri = useBlurSync(!bestImageData && message && getMessageMediaThumbDataUri(message));\n if (!bestImageData && origin !== MediaViewerOrigin.SearchResult) {\n bestImageData = thumbDataUri;\n }\n\n const photoDimensions = isPhoto ? getPhotoFullDimensions((\n isWebPagePhoto ? getMessageWebPagePhoto(message!) : getMessagePhoto(message!)\n )!) : undefined;\n const videoDimensions = isVideo ? getVideoDimensions(getMessageVideo(message!)!) : undefined;\n\n useEffect(() => {\n if (!IS_MOBILE_SCREEN) {\n return;\n }\n\n document.body.classList.toggle('is-media-viewer-open', isOpen);\n }, [isOpen]);\n\n const forceUpdate = useForceUpdate();\n useEffect(() => {\n const mql = window.matchMedia(MEDIA_VIEWER_MEDIA_QUERY);\n if (typeof mql.addEventListener === 'function') {\n mql.addEventListener('change', forceUpdate);\n } else if (typeof mql.addListener === 'function') {\n mql.addListener(forceUpdate);\n }\n\n return () => {\n if (typeof mql.removeEventListener === 'function') {\n mql.removeEventListener('change', forceUpdate);\n } else if (typeof mql.removeListener === 'function') {\n mql.removeListener(forceUpdate);\n }\n };\n }, [forceUpdate]);\n\n const prevMessage = usePrevious<ApiMessage | undefined>(message);\n const prevOrigin = usePrevious(origin);\n const prevAvatarOwner = usePrevious<ApiChat | ApiUser | undefined>(avatarOwner);\n const prevBestImageData = usePrevious(bestImageData);\n useEffect(() => {\n if (isGhostAnimation && isOpen && !prevMessage && !prevAvatarOwner) {\n dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);\n const textParts = message ? renderMessageText(message) : undefined;\n const hasFooter = Boolean(textParts);\n animateOpening(hasFooter, origin!, bestImageData!, message);\n }\n\n if (isGhostAnimation && !isOpen && (prevMessage || prevAvatarOwner)) {\n dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY);\n animateClosing(prevOrigin!, prevBestImageData!, prevMessage || undefined);\n }\n }, [\n isGhostAnimation, isOpen, origin, prevOrigin,\n message, prevMessage, prevAvatarOwner, bestImageData, prevBestImageData,\n ]);\n\n useEffect(() => {\n let timer: number | undefined;\n\n if (isZoomed) {\n setCanPanZoomWrap(true);\n } else {\n timer = window.setTimeout(() => {\n setCanPanZoomWrap(false);\n }, ANIMATION_DURATION);\n }\n\n return () => {\n if (timer) {\n window.clearTimeout(timer);\n }\n };\n }, [isZoomed]);\n\n const closeZoom = () => {\n setIsZoomed(false);\n setZoomLevel(1);\n setPanDelta({ x: 0, y: 0 });\n };\n\n const handleZoomToggle = useCallback(() => {\n setIsZoomed(!isZoomed);\n setZoomLevel(!isZoomed ? 1.5 : 1);\n if (isZoomed) {\n setPanDelta({ x: 0, y: 0 });\n }\n }, [isZoomed]);\n\n const handleZoomValue = useCallback((level: number, canCloseZoom = false) => {\n setZoomLevel(level);\n if (level === 1 && canCloseZoom) {\n closeZoom();\n }\n }, []);\n\n const close = useCallback(() => {\n closeMediaViewer();\n closeZoom();\n }, [closeMediaViewer]);\n\n const handleFooterClick = useCallback(() => {\n close();\n focusMessage({ chatId, threadId, messageId });\n }, [close, chatId, threadId, focusMessage, messageId]);\n\n const handleForward = useCallback(() => {\n openForwardMenu({ fromChatId: chatId, messageIds: [messageId] });\n closeZoom();\n }, [openForwardMenu, chatId, messageId]);\n\n useEffect(() => (isOpen ? captureEscKeyListener(() => {\n if (isZoomed) {\n closeZoom();\n } else {\n close();\n }\n }) : undefined), [close, isOpen, isZoomed]);\n\n useEffect(() => {\n if (isVideo && !isGif) {\n stopCurrentAudio();\n }\n }, [isGif, isVideo]);\n\n const getMessageId = useCallback((fromId: number, direction: number): number => {\n let index = messageIds.indexOf(fromId);\n if ((direction === -1 && index > 0) || (direction === 1 && index < messageIds.length - 1)) {\n index += direction;\n }\n\n return messageIds[index];\n }, [messageIds]);\n\n const selectPreviousMedia = useCallback(() => {\n if (isFirst) {\n return;\n }\n\n openMediaViewer({\n chatId,\n threadId,\n messageId: messageId ? getMessageId(messageId, -1) : undefined,\n origin,\n });\n }, [chatId, threadId, getMessageId, isFirst, messageId, openMediaViewer, origin]);\n\n const selectNextMedia = useCallback(() => {\n if (isLast) {\n return;\n }\n\n openMediaViewer({\n chatId,\n threadId,\n messageId: messageId ? getMessageId(messageId, 1) : undefined,\n origin,\n });\n }, [chatId, threadId, getMessageId, isLast, messageId, openMediaViewer, origin]);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'Left': // IE/Edge specific value\n case 'ArrowLeft':\n selectPreviousMedia();\n break;\n\n case 'Right': // IE/Edge specific value\n case 'ArrowRight':\n selectNextMedia();\n break;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown, false);\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown, false);\n };\n });\n\n // Support for swipe gestures and closing on click\n useEffect(() => {\n const element = document.querySelector<HTMLDivElement>('.slide-container > .active, .slide-container > .to');\n if (!element) {\n return undefined;\n }\n\n const shouldCloseOnVideo = isGif && !IS_IOS;\n\n return captureEvents(element, {\n // eslint-disable-next-line max-len\n excludedClosestSelector: `.backdrop, .navigation, .media-viewer-head, .media-viewer-footer${!shouldCloseOnVideo ? ', .VideoPlayer' : ''}`,\n onClick: () => {\n if (!isZoomed) {\n close();\n }\n },\n onSwipe: IS_TOUCH_ENV ? (e, direction) => {\n if (direction === SwipeDirection.Right) {\n selectPreviousMedia();\n } else if (direction === SwipeDirection.Left) {\n selectNextMedia();\n } else {\n close();\n }\n } : undefined,\n });\n }, [close, isGif, isZoomed, selectNextMedia, selectPreviousMedia, canPanZoomWrap]);\n\n const handlePan = useCallback((x: number, y: number) => {\n setPanDelta({ x, y });\n }, []);\n\n const lang = useLang();\n\n function renderSlide(isActive: boolean) {\n if (avatarOwner) {\n return (\n <div key={chatId} className=\"media-viewer-content\">\n {renderPhoto(fullMediaData || blobUrlPreview, calculateMediaViewerDimensions(AVATAR_FULL_DIMENSIONS, false))}\n </div>\n );\n } else if (message) {\n const textParts = renderMessageText(message);\n const hasFooter = Boolean(textParts);\n\n return (\n <div key={messageId} className={`media-viewer-content ${hasFooter ? 'has-footer' : ''}`}>\n {isPhoto && renderPhoto(\n localBlobUrl || fullMediaData || blobUrlPreview || blobUrlPictogram,\n message && calculateMediaViewerDimensions(photoDimensions!, hasFooter),\n )}\n {isVideo && (\n <VideoPlayer\n key={messageId}\n url={localBlobUrl || fullMediaData}\n isGif={isGif}\n posterData={bestImageData}\n posterSize={message && calculateMediaViewerDimensions(videoDimensions!, hasFooter, true)}\n downloadProgress={downloadProgress}\n fileSize={video!.size}\n isMediaViewerOpen={isOpen}\n noPlay={!isActive}\n onClose={close}\n />\n )}\n {textParts && (\n <MediaViewerFooter\n text={textParts}\n onClick={handleFooterClick}\n isHideable={isVideo}\n />\n )}\n </div>\n );\n }\n\n return undefined;\n }\n\n function renderSenderInfo() {\n return (\n <SenderInfo\n key={avatarOwner ? avatarOwner.id : messageId}\n chatId={avatarOwner ? avatarOwner.id : chatId}\n messageId={messageId}\n isAvatar={Boolean(avatarOwner)}\n />\n );\n }\n\n return (\n <ShowTransition\n id=\"MediaViewer\"\n className={isZoomed ? 'zoomed' : ''}\n isOpen={isOpen}\n >\n {() => (\n <>\n <div className=\"media-viewer-head\">\n {IS_MOBILE_SCREEN && (\n <Button\n className=\"media-viewer-close\"\n round\n size=\"smaller\"\n color=\"translucent-white\"\n ariaLabel={lang('Close')}\n onClick={close}\n >\n <i className=\"icon-close\" />\n </Button>\n )}\n <Transition activeKey={animationKey.current!} name={headerAnimation}>\n {renderSenderInfo}\n </Transition>\n <MediaViewerActions\n mediaData={fullMediaData || blobUrlPreview}\n isVideo={isVideo}\n isZoomed={isZoomed}\n message={message}\n fileName={fileName}\n onCloseMediaViewer={close}\n onForward={handleForward}\n onZoomToggle={handleZoomToggle}\n isAvatar={Boolean(avatarOwner)}\n />\n </div>\n <PanZoom\n noWrap={!canPanZoomWrap}\n canPan={isZoomed}\n panDeltaX={panDelta.x}\n panDeltaY={panDelta.y}\n zoomLevel={zoomLevel}\n onPan={handlePan}\n >\n <Transition\n className=\"slide-container\"\n activeKey={selectedMediaMessageIndex}\n name={slideAnimation}\n >\n {renderSlide}\n </Transition>\n </PanZoom>\n {!isFirst && (\n <button\n type=\"button\"\n className={`navigation prev ${isVideo && !isGif && 'inline'}`}\n aria-label={lang('AccDescrPrevious')}\n onClick={selectPreviousMedia}\n />\n )}\n {!isLast && (\n <button\n type=\"button\"\n className={`navigation next ${isVideo && !isGif && 'inline'}`}\n aria-label={lang('Next')}\n onClick={selectNextMedia}\n />\n )}\n <ZoomControls\n isShown={isZoomed}\n onChangeZoom={handleZoomValue}\n />\n </>\n )}\n </ShowTransition>\n );\n};\n\nfunction renderPhoto(blobUrl?: string, imageSize?: IDimensions) {\n return blobUrl\n ? (\n <img\n src={blobUrl}\n alt=\"\"\n // @ts-ignore teact feature\n style={imageSize ? `width: ${imageSize.width}px` : ''}\n draggable={false}\n />\n )\n : (\n <div\n className=\"spinner-wrapper\"\n // @ts-ignore teact feature\n style={imageSize ? `width: ${imageSize.width}px` : ''}\n >\n <Spinner color=\"white\" />\n </div>\n );\n}\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const {\n chatId, threadId, messageId, avatarOwnerId, origin,\n } = global.mediaViewer;\n const {\n animationLevel,\n } = global.settings.byKey;\n\n if (origin === MediaViewerOrigin.SearchResult) {\n if (!(chatId && messageId)) {\n return { animationLevel };\n }\n\n const message = selectChatMessage(global, chatId, messageId);\n if (!message) {\n return { animationLevel };\n }\n\n return {\n chatId,\n messageId,\n senderId: message.senderId,\n origin,\n message,\n animationLevel,\n };\n }\n\n if (avatarOwnerId) {\n const sender = selectChat(global, avatarOwnerId) || selectUser(global, avatarOwnerId);\n\n return {\n messageId: -1,\n senderId: avatarOwnerId,\n avatarOwner: sender,\n animationLevel,\n origin,\n };\n }\n\n if (!(chatId && threadId && messageId)) {\n return { animationLevel };\n }\n\n let message: ApiMessage | undefined;\n if (origin && [MediaViewerOrigin.ScheduledAlbum, MediaViewerOrigin.ScheduledInline].includes(origin)) {\n message = selectScheduledMessage(global, chatId, messageId);\n } else {\n message = selectChatMessage(global, chatId, messageId);\n }\n\n if (!message) {\n return { animationLevel };\n }\n\n let chatMessages: Record<number, ApiMessage> | undefined;\n\n if (origin && [MediaViewerOrigin.ScheduledAlbum, MediaViewerOrigin.ScheduledInline].includes(origin)) {\n chatMessages = selectScheduledMessages(global, chatId);\n } else {\n chatMessages = selectChatMessages(global, chatId);\n }\n let collectionIds: number[] | undefined;\n\n if (origin === MediaViewerOrigin.Inline || origin === MediaViewerOrigin.Album) {\n collectionIds = selectOutlyingIds(global, chatId, threadId) || selectListedIds(global, chatId, threadId);\n } else if (origin === MediaViewerOrigin.SharedMedia) {\n const currentSearch = selectCurrentMediaSearch(global);\n const { foundIds } = (currentSearch && currentSearch.resultsByType && currentSearch.resultsByType.media) || {};\n collectionIds = foundIds;\n }\n\n return {\n chatId,\n threadId,\n messageId,\n senderId: message.senderId,\n origin,\n message,\n chatMessages,\n collectionIds,\n animationLevel,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'openMediaViewer', 'closeMediaViewer', 'openForwardMenu', 'focusMessage',\n ]),\n)(MediaViewer));\n","import { useRef } from '../lib/teact/teact';\n\nimport fastBlur from '../lib/fastBlur';\nimport useOnChange from './useOnChange';\nimport useBlur from './useBlur';\nimport { imgToCanvas } from '../util/files';\n\nconst RADIUS = 2;\nconst ITERATIONS = 2;\n\nexport default function useBlurSync(dataUri: string | false | undefined) {\n const blurredRef = useRef<string>();\n\n let isChanged = false;\n\n useOnChange(() => {\n isChanged = true;\n\n blurredRef.current = undefined;\n\n if (!dataUri) {\n return;\n }\n\n const img = new Image();\n img.src = dataUri;\n if (!img.width) {\n return;\n }\n\n const canvas = imgToCanvas(img);\n fastBlur(canvas.getContext('2d'), 0, 0, canvas.width, canvas.height, RADIUS, ITERATIONS);\n\n blurredRef.current = canvas.toDataURL();\n }, [dataUri]);\n\n // Sometimes `Image` do not manage to load synchronously,\n // so we fall back the non-blurred variant and prepare the async one at least for the next time\n const blurredAsync = useBlur(dataUri || undefined, Boolean(blurredRef.current));\n\n return blurredRef.current || (!isChanged && blurredAsync) || dataUri || undefined;\n}\n","import React, {\n FC, useMemo, useState, memo, useRef, useEffect, useCallback,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiChat, ApiUser } from '../../api/types';\n\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport { getChatTitle, prepareChatList, isChatPrivate } from '../../modules/helpers';\nimport { selectUser } from '../../modules/selectors';\nimport searchWords from '../../util/searchWords';\nimport { pick } from '../../util/iteratees';\nimport useInfiniteScroll from '../../hooks/useInfiniteScroll';\nimport useLang from '../../hooks/useLang';\n\nimport Loading from '../ui/Loading';\nimport Modal from '../ui/Modal';\nimport InputText from '../ui/InputText';\nimport Button from '../ui/Button';\nimport InfiniteScroll from '../ui/InfiniteScroll';\nimport ListItem from '../ui/ListItem';\nimport PrivateChatInfo from '../common/PrivateChatInfo';\nimport GroupChatInfo from '../common/GroupChatInfo';\n\nimport './ForwardPicker.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n};\n\ntype StateProps = {\n chatsById: Record<number, ApiChat>;\n listIds?: number[];\n orderedPinnedIds?: number[];\n currentUser?: ApiUser;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setForwardChatId' | 'exitForwardMode' | 'loadMoreChats'>;\n\n// Focus slows down animation, also it breaks transition layout in Chrome\nconst FOCUS_DELAY_MS = 500;\nconst MODAL_HIDE_DELAY_MS = 300;\n\nconst ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({\n chatsById,\n listIds,\n orderedPinnedIds,\n currentUser,\n isOpen,\n setForwardChatId,\n exitForwardMode,\n loadMoreChats,\n}) => {\n const [filter, setFilter] = useState('');\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (isOpen) {\n if (!IS_MOBILE_SCREEN) {\n setTimeout(() => {\n requestAnimationFrame(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n });\n }, FOCUS_DELAY_MS);\n }\n } else {\n if (inputRef.current) {\n inputRef.current.blur();\n }\n\n setTimeout(() => {\n setFilter('');\n }, MODAL_HIDE_DELAY_MS);\n }\n }, [isOpen]);\n\n const chats = useMemo(() => {\n const chatArrays = listIds ? prepareChatList(chatsById, listIds, orderedPinnedIds) : undefined;\n if (!chatArrays) {\n return undefined;\n }\n\n const chatWithSelf = currentUser ? chatsById[currentUser.id] : undefined;\n\n return [\n ...(chatWithSelf ? [chatWithSelf] : []),\n ...chatArrays.pinnedChats.filter(({ id }) => !chatWithSelf || id !== chatWithSelf.id),\n ...chatArrays.otherChats.filter(({ id }) => !chatWithSelf || id !== chatWithSelf.id),\n ];\n }, [chatsById, listIds, orderedPinnedIds, currentUser]);\n\n const chatIds = useMemo(() => {\n if (!chats) {\n return undefined;\n }\n\n return chats\n .filter((chat) => (!filter || searchWords(getChatTitle(chat, currentUser), filter)))\n .map(({ id }) => id);\n }, [chats, filter, currentUser]);\n\n const [viewportIds, getMore] = useInfiniteScroll(loadMoreChats, chatIds, Boolean(filter));\n\n const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setFilter(e.currentTarget.value);\n }, []);\n\n const lang = useLang();\n\n const modalHeader = (\n <div className=\"modal-header\">\n <Button\n round\n color=\"translucent\"\n size=\"smaller\"\n ariaLabel={lang('Close')}\n onClick={exitForwardMode}\n >\n <i className=\"icon-close\" />\n </Button>\n <InputText\n ref={inputRef}\n value={filter}\n onChange={handleFilterChange}\n placeholder={lang('ForwardTo')}\n />\n </div>\n );\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={exitForwardMode}\n className=\"ForwardPicker\"\n header={modalHeader}\n >\n {viewportIds && viewportIds.length ? (\n <InfiniteScroll\n className=\"picker-list custom-scroll\"\n items={viewportIds}\n onLoadMore={getMore}\n isDisabled={Boolean(filter)}\n >\n {viewportIds.map((id) => (\n <ListItem\n key={id}\n className=\"chat-item-clickable force-rounded-corners\"\n onClick={() => setForwardChatId({ id })}\n >\n {isChatPrivate(id) ? (\n <PrivateChatInfo userId={id} />\n ) : (\n <GroupChatInfo chatId={id} />\n )}\n </ListItem>\n ))}\n </InfiniteScroll>\n ) : viewportIds && !viewportIds.length ? (\n <p className=\"no-results\">Sorry, nothing found.</p>\n ) : (\n <Loading />\n )}\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n chats: {\n byId: chatsById,\n listIds,\n orderedPinnedIds,\n },\n currentUserId,\n } = global;\n\n return {\n chatsById,\n listIds: listIds.active,\n orderedPinnedIds: orderedPinnedIds.active,\n currentUser: currentUserId ? selectUser(global, currentUserId) : undefined,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['setForwardChatId', 'exitForwardMode', 'loadMoreChats']),\n)(ForwardPicker));\n","import React, { FC, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiError } from '../../api/types';\n\nimport getReadableErrorText from '../../util/getReadableErrorText';\nimport { pick } from '../../util/iteratees';\nimport useLang from '../../hooks/useLang';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nimport './Errors.scss';\n\ntype StateProps = {\n errors: ApiError[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'dismissError'>;\n\nconst Errors: FC<StateProps & DispatchProps> = ({ errors, dismissError }) => {\n const lang = useLang();\n\n if (!errors.length) {\n return undefined;\n }\n\n return (\n <div id=\"Errors\">\n {errors.map((error) => (\n <Modal\n isOpen\n onClose={dismissError}\n className=\"error\"\n title={getErrorHeader(error)}\n >\n <p>{getReadableErrorText(error)}</p>\n <Button isText onClick={dismissError}>{lang('OK')}</Button>\n </Modal>\n ))}\n </div>\n );\n};\n\nfunction getErrorHeader(error: ApiError) {\n if (error.isSlowMode) {\n return 'Slowmode enabled';\n }\n\n return 'Something went wrong';\n}\n\nexport default memo(withGlobal(\n (global): StateProps => pick(global, ['errors']),\n (setGlobal, actions): DispatchProps => pick(actions, ['dismissError']),\n)(Errors));\n","import React, { FC, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiNotification } from '../../api/types';\n\nimport { pick } from '../../util/iteratees';\n\nimport Notification from '../ui/Notification';\nimport renderText from '../common/helpers/renderText';\n\ntype StateProps = {\n notifications: ApiNotification[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'dismissNotification'>;\n\nconst Notifications: FC<StateProps & DispatchProps> = ({ notifications, dismissNotification }) => {\n if (!notifications.length) {\n return undefined;\n }\n\n return (\n <div id=\"Notifications\">\n {notifications.map(({ message }) => (\n <Notification\n message={renderText(message, ['emoji', 'br', 'links'])}\n onDismiss={dismissNotification}\n />\n ))}\n </div>\n );\n};\n\nexport default memo(withGlobal(\n (global): StateProps => pick(global, ['notifications']),\n (setGlobal, actions): DispatchProps => pick(actions, ['dismissNotification']),\n)(Notifications));\n","import React, {\n FC, memo, useState, useEffect, useMemo, useCallback,\n} from '../../lib/teact/teact';\n\nimport buildClassName from '../../util/buildClassName';\nimport {\n formatMonthAndYear, formatHumanDate, formatTime,\n} from '../../util/dateFormat';\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nimport './CalendarModal.scss';\n\nexport type OwnProps = {\n selectedAt?: number;\n maxAt?: number;\n isFutureMode?: boolean;\n isPastMode?: boolean;\n isOpen: boolean;\n withTimePicker?: boolean;\n submitButtonLabel?: string;\n secondButtonLabel?: string;\n onClose: () => void;\n onSubmit: (date: Date) => void;\n onSecondButtonClick?: NoneToVoidFunction;\n};\n\nconst WEEKDAY_LETTERS = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];\n\nconst CalendarModal: FC<OwnProps> = ({\n selectedAt,\n maxAt,\n isFutureMode,\n isPastMode,\n isOpen,\n withTimePicker,\n submitButtonLabel,\n secondButtonLabel,\n onClose,\n onSubmit,\n onSecondButtonClick,\n}) => {\n const now = new Date();\n const defaultSelectedDate = useMemo(() => (selectedAt ? new Date(selectedAt) : new Date()), [selectedAt]);\n const maxDate = maxAt ? new Date(maxAt) : undefined;\n\n const [selectedDate, setSelectedDate] = useState<Date>(defaultSelectedDate);\n const [selectedHours, setSelectedHours] = useState<string>(\n formatInputTime(defaultSelectedDate.getHours()),\n );\n const [selectedMinutes, setSelectedMinutes] = useState<string>(\n formatInputTime(defaultSelectedDate.getMinutes()),\n );\n\n const currentYear = selectedDate.getFullYear();\n const currentMonth = selectedDate.getMonth();\n const currentDate = selectedDate.getDate();\n\n useEffect(() => {\n if (isOpen) {\n setSelectedDate(defaultSelectedDate);\n }\n }, [isOpen, defaultSelectedDate]);\n\n const shouldDisableNextMonth = (isPastMode && currentYear >= now.getFullYear() && currentMonth >= now.getMonth())\n || (maxDate && currentYear >= maxDate.getFullYear() && currentMonth >= maxDate.getMonth());\n const shouldDisablePrevMonth = isFutureMode && currentYear <= now.getFullYear() && currentMonth <= now.getMonth();\n\n const calendarGrid = useMemo(() => (\n buildCalendarGrid(currentYear, currentMonth)\n ), [currentMonth, currentYear]);\n\n function handlePrevMonth() {\n setSelectedDate((d) => {\n const dateCopy = new Date(d);\n dateCopy.setMonth(dateCopy.getMonth() - 1);\n\n return dateCopy;\n });\n }\n\n function handleNextMonth() {\n setSelectedDate((d) => {\n const dateCopy = new Date(d);\n dateCopy.setMonth(dateCopy.getMonth() + 1);\n\n return dateCopy;\n });\n }\n\n function handleDateSelect(date: number) {\n setSelectedDate((d) => {\n const dateCopy = new Date(d);\n dateCopy.setDate(date);\n\n return dateCopy;\n });\n }\n\n function handleSubmit() {\n onSubmit(selectedDate);\n }\n\n const handleChangeHours = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value.replace(/[^\\d]+/g, '');\n if (!value.length) {\n setSelectedHours('');\n e.target.value = '';\n return;\n }\n\n const hours = Math.max(0, Math.min(Number(value), 23));\n\n const date = new Date(selectedDate.getTime());\n date.setHours(hours);\n setSelectedDate(date);\n\n const hoursStr = formatInputTime(hours);\n setSelectedHours(hoursStr);\n e.target.value = hoursStr;\n }, [selectedDate]);\n\n const handleChangeMinutes = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value.replace(/[^\\d]+/g, '');\n if (!value.length) {\n setSelectedMinutes('');\n e.target.value = '';\n return;\n }\n\n const minutes = Math.max(0, Math.min(Number(value), 59));\n\n const date = new Date(selectedDate.getTime());\n date.setMinutes(minutes);\n setSelectedDate(date);\n\n const minutesStr = formatInputTime(minutes);\n setSelectedMinutes(minutesStr);\n e.target.value = minutesStr;\n }, [selectedDate]);\n\n function renderTimePicker() {\n return (\n <div className=\"timepicker\">\n <input\n type=\"text\"\n className=\"form-control\"\n inputMode=\"decimal\"\n value={selectedHours}\n onChange={handleChangeHours}\n />\n :\n <input\n type=\"text\"\n className=\"form-control\"\n inputMode=\"decimal\"\n value={selectedMinutes}\n onChange={handleChangeMinutes}\n />\n </div>\n );\n }\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n className=\"CalendarModal\"\n >\n <div className=\"container\">\n <div className=\"month-selector\">\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={onClose}\n >\n <i className=\"icon-close\" />\n </Button>\n\n <h4>\n {formatMonthAndYear(selectedDate, IS_MOBILE_SCREEN)}\n </h4>\n\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n disabled={shouldDisablePrevMonth}\n onClick={!shouldDisablePrevMonth ? handlePrevMonth : undefined}\n >\n <i className=\"icon-previous\" />\n </Button>\n\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n disabled={shouldDisableNextMonth}\n onClick={!shouldDisableNextMonth ? handleNextMonth : undefined}\n >\n <i className=\"icon-next\" />\n </Button>\n </div>\n </div>\n\n <div className=\"calendar-wrapper\">\n <div className=\"calendar-grid\">\n {WEEKDAY_LETTERS.map((letter) => (\n <div className=\"day-button faded weekday\">\n <span>{letter}</span>\n </div>\n ))}\n {calendarGrid.map((gridDate) => (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => handleDateSelect(gridDate)}\n className={buildClassName(\n 'day-button',\n isDisabledDay(\n currentYear, currentMonth, gridDate, isFutureMode ? now : undefined, isPastMode ? now : maxDate,\n )\n ? 'disabled'\n : `${gridDate ? 'clickable' : ''}`,\n gridDate === currentDate && 'selected',\n )}\n >\n {!!gridDate && (\n <span>{gridDate}</span>\n )}\n </div>\n ))}\n </div>\n </div>\n\n {withTimePicker && renderTimePicker()}\n\n <div className=\"footer\">\n <Button onClick={handleSubmit}>\n {withTimePicker ? formatSubmitLabel(selectedDate) : submitButtonLabel}\n </Button>\n {secondButtonLabel && (\n <Button onClick={onSecondButtonClick} isText>\n {secondButtonLabel}\n </Button>\n )}\n </div>\n </Modal>\n );\n};\n\nfunction buildCalendarGrid(year: number, month: number) {\n const grid: number[] = [];\n\n const date = new Date();\n date.setFullYear(year);\n date.setMonth(month);\n date.setDate(1);\n\n const monthStartDay = date.getDay();\n // Fill empty cells\n for (let i = 1; i < monthStartDay; i++) {\n grid.push(0);\n }\n\n while (date.getMonth() === month) {\n const gridDate = date.getDate();\n grid.push(gridDate);\n date.setDate(gridDate + 1);\n }\n\n return grid;\n}\n\nfunction isDisabledDay(year: number, month: number, day: number, minDate?: Date, maxDate?: Date) {\n const selectedDay = new Date(year, month, day, 0, 0, 0, 0);\n const fixedMinDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), 0, 0, 0, 0);\n const fixedMaxDate = maxDate && new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 0, 0, 0, 0);\n\n if (fixedMaxDate && selectedDay > fixedMaxDate) {\n return true;\n } else if (fixedMinDate && selectedDay < fixedMinDate) {\n return true;\n }\n\n return false;\n}\n\nfunction formatInputTime(value: string | number) {\n return String(value).padStart(2, '0');\n}\n\nfunction formatSubmitLabel(date: Date) {\n const day = formatHumanDate(date, true);\n\n return `Send ${day === 'Today' ? day : `on ${day}`} at ${formatTime(date)}`;\n}\n\nexport default memo(CalendarModal);\n","import React, { FC, useCallback, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiMessage } from '../../api/types';\nimport { IAlbum } from '../../types';\n\nimport { GlobalActions } from '../../global/types';\n\nimport {\n selectAllowedMessageActions,\n selectChat,\n selectCurrentMessageList,\n selectUser,\n} from '../../modules/selectors';\nimport {\n isChatPrivate,\n getUserFirstOrLastName,\n getPrivateChatUserId,\n isChatBasicGroup,\n isChatSuperGroup,\n} from '../../modules/helpers';\nimport renderText from './helpers/renderText';\nimport { pick } from '../../util/iteratees';\nimport useLang from '../../hooks/useLang';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nexport type OwnProps = {\n isOpen: boolean;\n isSchedule: boolean;\n message: ApiMessage;\n album?: IAlbum;\n onClose: () => void;\n};\n\ntype StateProps = {\n canDeleteForAll?: boolean;\n contactName?: string;\n willDeleteForCurrentUserOnly?: boolean;\n willDeleteForAll?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'deleteMessages' | 'deleteScheduledMessages'>;\n\nconst DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n isSchedule,\n message,\n album,\n canDeleteForAll,\n contactName,\n willDeleteForCurrentUserOnly,\n willDeleteForAll,\n onClose,\n deleteMessages,\n deleteScheduledMessages,\n}) => {\n const handleDeleteMessageForAll = useCallback(() => {\n const messageIds = album && album.messages\n ? album.messages.map(({ id }) => id)\n : [message.id];\n deleteMessages({ messageIds, shouldDeleteForAll: true });\n onClose();\n }, [deleteMessages, message.id, onClose, album]);\n\n const handleDeleteMessageForSelf = useCallback(() => {\n const messageIds = album && album.messages\n ? album.messages.map(({ id }) => id)\n : [message.id];\n if (isSchedule) {\n deleteScheduledMessages({ messageIds });\n } else {\n deleteMessages({\n messageIds,\n shouldDeleteForAll: false,\n });\n }\n onClose();\n }, [album, message.id, isSchedule, onClose, deleteScheduledMessages, deleteMessages]);\n\n const lang = useLang();\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n onEnter={isOpen && !canDeleteForAll ? handleDeleteMessageForSelf : undefined}\n className=\"delete\"\n title={lang('DeleteSingleMessagesTitle')}\n >\n <p>{lang('AreYouSureDeleteSingleMessage')}</p>\n {willDeleteForCurrentUserOnly && (\n <p>This will delete it just for you, not for other participants in the chat.</p>\n )}\n {willDeleteForAll && (\n <p>This will delete it for everyone in this chat.</p>\n )}\n {canDeleteForAll && (\n <Button color=\"danger\" className=\"confirm-dialog-button\" isText onClick={handleDeleteMessageForAll}>\n Delete for {contactName ? 'me and ' : 'Everyone'}\n {contactName && renderText(contactName)}\n </Button>\n )}\n <Button color=\"danger\" className=\"confirm-dialog-button\" isText onClick={handleDeleteMessageForSelf}>\n Delete{canDeleteForAll ? ' just for me' : ''}\n </Button>\n <Button className=\"confirm-dialog-button\" isText onClick={onClose}>{lang('Cancel')}</Button>\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { message, isSchedule }): StateProps => {\n const { threadId } = selectCurrentMessageList(global) || {};\n const { canDeleteForAll } = (threadId && selectAllowedMessageActions(global, message, threadId)) || {};\n const chat = selectChat(global, message.chatId);\n const contactName = chat && isChatPrivate(chat.id)\n ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))\n : undefined;\n\n const willDeleteForCurrentUserOnly = chat && isChatBasicGroup(chat) && !canDeleteForAll;\n const willDeleteForAll = chat && isChatSuperGroup(chat);\n\n return {\n canDeleteForAll: !isSchedule && canDeleteForAll,\n contactName,\n willDeleteForCurrentUserOnly,\n willDeleteForAll,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'deleteMessages', 'deleteScheduledMessages',\n ]),\n)(DeleteMessageModal));\n","import React, { FC, useCallback, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\n\nimport { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors';\nimport {\n isChatPrivate,\n getUserFirstOrLastName,\n getPrivateChatUserId,\n isChatBasicGroup,\n isChatSuperGroup,\n isChatChannel,\n} from '../../modules/helpers';\nimport { pick } from '../../util/iteratees';\nimport useLang from '../../hooks/useLang';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nexport type OwnProps = {\n isOpen: boolean;\n chatId: number;\n messageId: number;\n onClose: () => void;\n};\n\ntype StateProps = {\n isChannel: boolean;\n isPrivateChat: boolean;\n isChatWithSelf: boolean;\n isGroup: boolean;\n isSuperGroup: boolean;\n canPinForAll: boolean;\n contactName?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'pinMessage'>;\n\nconst PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n messageId,\n chatId,\n isChannel,\n isGroup,\n isSuperGroup,\n canPinForAll,\n contactName,\n onClose,\n pinMessage,\n}) => {\n const handlePinMessageForAll = useCallback(() => {\n pinMessage({\n chatId, messageId, isUnpin: false,\n });\n onClose();\n }, [pinMessage, chatId, messageId, onClose]);\n\n const handlePinMessage = useCallback(() => {\n pinMessage({\n chatId, messageId, isUnpin: false, isOneSide: true, isSilent: true,\n });\n onClose();\n }, [chatId, messageId, onClose, pinMessage]);\n\n const lang = useLang();\n\n function renderModalHeader() {\n return (\n <div className=\"modal-header\">\n <h3 className=\"modal-title\">{lang('PinMessageAlertTitle')}</h3>\n </div>\n );\n }\n\n function renderMessage() {\n if (isChannel) {\n return <p>{lang('PinMessageAlertChannel')}</p>;\n }\n\n if (isGroup || isSuperGroup) {\n return <p>{lang('PinMessageAlert')}</p>;\n }\n\n return <p>{lang('PinMessageAlertChat')}</p>;\n }\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n className=\"pin\"\n header={renderModalHeader()}\n >\n {renderMessage()}\n <Button className=\"confirm-dialog-button\" isText onClick={handlePinMessage}>\n {lang('DialogPin')}\n </Button>\n {canPinForAll && (\n <Button className=\"confirm-dialog-button\" isText onClick={handlePinMessageForAll}>\n {contactName ? `Pin for me and ${contactName}` : 'Pin and notify all memebers'}\n </Button>\n )}\n <Button className=\"confirm-dialog-button\" isText onClick={onClose}>{lang('Cancel')}</Button>\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const isPrivateChat = isChatPrivate(chatId);\n const isChatWithSelf = selectIsChatWithSelf(global, chatId);\n const chat = selectChat(global, chatId);\n const isChannel = !!chat && isChatChannel(chat);\n const isGroup = !!chat && isChatBasicGroup(chat);\n const isSuperGroup = !!chat && isChatSuperGroup(chat);\n const canPinForAll = (isPrivateChat && !isChatWithSelf) || isSuperGroup || isGroup;\n const contactName = chat && isChatPrivate(chat.id)\n ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))\n : undefined;\n\n return {\n isPrivateChat,\n isChatWithSelf,\n isChannel,\n isGroup,\n isSuperGroup,\n canPinForAll,\n contactName,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['pinMessage']),\n)(PinMessageModal));\n","import React, { FC, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { selectPinnedIds } from '../../modules/selectors';\nimport useLang from '../../hooks/useLang';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nexport type OwnProps = {\n isOpen: boolean;\n chatId?: number;\n onClose: () => void;\n onUnpin: () => void;\n};\n\ntype StateProps = {\n pinnedMessagesCount: number;\n};\n\nconst UnpinAllMessagesModal: FC<OwnProps & StateProps> = ({\n isOpen,\n pinnedMessagesCount,\n onClose,\n onUnpin,\n}) => {\n const lang = useLang();\n\n function renderModalHeader() {\n return (\n <div className=\"modal-header\">\n <h3 className=\"modal-title\">{lang('UnpinAllMessages')}</h3>\n </div>\n );\n }\n\n function renderMessage() {\n return <p>Do you want to unpin all {pinnedMessagesCount} messages in this chat?</p>;\n }\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n className=\"unpin-all\"\n header={renderModalHeader()}\n >\n {renderMessage()}\n <Button className=\"confirm-dialog-button\" isText onClick={onUnpin}>\n {lang('DialogUnpin')}\n </Button>\n <Button className=\"confirm-dialog-button\" isText onClick={onClose}>{lang('Cancel')}</Button>\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const pinnedIds = chatId ? selectPinnedIds(global, chatId) : [];\n\n return {\n pinnedMessagesCount: pinnedIds ? pinnedIds.length : 0,\n };\n },\n)(UnpinAllMessagesModal));\n","import React, { FC, useCallback, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\n\nimport { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors';\nimport {\n isChatPrivate,\n getUserFirstOrLastName,\n getPrivateChatUserId,\n isChatBasicGroup,\n isChatSuperGroup,\n} from '../../modules/helpers';\nimport renderText from '../common/helpers/renderText';\nimport { pick } from '../../util/iteratees';\nimport useLang from '../../hooks/useLang';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nexport type OwnProps = {\n isOpen: boolean;\n isSchedule: boolean;\n onClose: () => void;\n};\n\ntype StateProps = {\n selectedMessageIds?: number[];\n canDeleteForAll?: boolean;\n contactName?: string;\n willDeleteForCurrentUserOnly?: boolean;\n willDeleteForAll?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'deleteMessages' | 'exitMessageSelectMode' | 'deleteScheduledMessages'>;\n\nconst DeleteSelectedMessagesModal: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n isSchedule,\n selectedMessageIds,\n canDeleteForAll,\n contactName,\n willDeleteForCurrentUserOnly,\n willDeleteForAll,\n onClose,\n deleteMessages,\n deleteScheduledMessages,\n exitMessageSelectMode,\n}) => {\n const handleDeleteMessageForAll = useCallback(() => {\n deleteMessages({ messageIds: selectedMessageIds, shouldDeleteForAll: true });\n exitMessageSelectMode();\n onClose();\n }, [deleteMessages, exitMessageSelectMode, selectedMessageIds, onClose]);\n\n const handleDeleteMessageForSelf = useCallback(() => {\n if (isSchedule) {\n deleteScheduledMessages({ messageIds: selectedMessageIds });\n } else {\n deleteMessages({ messageIds: selectedMessageIds, shouldDeleteForAll: false });\n }\n\n exitMessageSelectMode();\n onClose();\n }, [\n isSchedule, exitMessageSelectMode, onClose, deleteScheduledMessages, selectedMessageIds, deleteMessages,\n ]);\n\n const lang = useLang();\n\n if (!selectedMessageIds) {\n return undefined;\n }\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n onEnter={canDeleteForAll ? undefined : handleDeleteMessageForSelf}\n className=\"delete\"\n title=\"Delete Messages?\"\n >\n <p>{lang('AreYouSureDeleteFewMessages')}</p>\n {willDeleteForCurrentUserOnly && (\n <p>This will delete them just for you, not for other participants in the chat.</p>\n )}\n {willDeleteForAll && (\n <p>This will delete them for everyone in this chat.</p>\n )}\n {canDeleteForAll && (\n <Button color=\"danger\" className=\"confirm-dialog-button\" isText onClick={handleDeleteMessageForAll}>\n Delete for {contactName ? 'me and ' : 'Everyone'}\n {contactName && renderText(contactName)}\n </Button>\n )}\n <Button color=\"danger\" className=\"confirm-dialog-button\" isText onClick={handleDeleteMessageForSelf}>\n Delete{canDeleteForAll ? ' just for me' : ''}\n </Button>\n <Button className=\"confirm-dialog-button\" isText onClick={onClose}>{lang('Cancel')}</Button>\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { isSchedule }): StateProps => {\n const { messageIds: selectedMessageIds } = global.selectedMessages || {};\n const { canDeleteForAll } = selectCanDeleteSelectedMessages(global);\n const chat = selectCurrentChat(global);\n const contactName = chat && isChatPrivate(chat.id)\n ? getUserFirstOrLastName(selectUser(global, getPrivateChatUserId(chat)!))\n : undefined;\n\n const willDeleteForCurrentUserOnly = chat && isChatBasicGroup(chat) && !canDeleteForAll;\n const willDeleteForAll = chat && isChatSuperGroup(chat);\n\n return {\n selectedMessageIds,\n canDeleteForAll: !isSchedule && canDeleteForAll,\n contactName,\n willDeleteForCurrentUserOnly,\n willDeleteForAll,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'deleteMessages',\n 'deleteScheduledMessages',\n 'exitMessageSelectMode',\n ]),\n)(DeleteSelectedMessagesModal));\n","import React, { FC, memo, useEffect } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions, MessageListType } from '../../global/types';\n\nimport {\n selectCanDeleteSelectedMessages,\n selectCurrentMessageList,\n selectSelectedMessagesCount,\n} from '../../modules/selectors';\nimport { pick } from '../../util/iteratees';\nimport useFlag from '../../hooks/useFlag';\nimport captureKeyboardListeners from '../../util/captureKeyboardListeners';\nimport buildClassName from '../../util/buildClassName';\nimport usePrevious from '../../hooks/usePrevious';\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\nimport MenuItem from '../ui/MenuItem';\n\nimport DeleteSelectedMessagesModal from './DeleteSelectedMessagesModal';\n\nimport './MessageSelectToolbar.scss';\n\nexport type OwnProps = {\n isActive?: boolean;\n canPost?: boolean;\n messageListType?: MessageListType;\n};\n\ntype StateProps = {\n isSchedule: boolean;\n selectedMessagesCount?: number;\n canDeleteMessages?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'exitMessageSelectMode' | 'openForwardMenuForSelectedMessages'>;\n\nconst MessageSelectToolbar: FC<OwnProps & StateProps & DispatchProps> = ({\n canPost,\n isActive,\n messageListType,\n isSchedule,\n selectedMessagesCount,\n canDeleteMessages,\n exitMessageSelectMode,\n openForwardMenuForSelectedMessages,\n}) => {\n const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag();\n\n useEffect(() => {\n return isActive && !isDeleteModalOpen\n ? captureKeyboardListeners({\n onBackspace: openDeleteModal,\n onDelete: openDeleteModal,\n onEsc: exitMessageSelectMode,\n })\n : undefined;\n }, [isActive, isDeleteModalOpen, openDeleteModal, exitMessageSelectMode]);\n\n const prevSelectedMessagesCount = usePrevious(selectedMessagesCount || undefined, true);\n const renderingSelectedMessagesCount = isActive ? selectedMessagesCount : prevSelectedMessagesCount;\n\n const lang = useLang();\n\n const formattedMessagesCount = lang('VoiceOver.Chat.MessagesSelected', renderingSelectedMessagesCount);\n\n const className = buildClassName(\n 'MessageSelectToolbar',\n canPost && 'with-composer',\n isActive && 'shown',\n );\n\n return (\n <div className={className}>\n <div className=\"MessageSelectToolbar-inner\">\n <Button\n color=\"translucent\"\n round\n onClick={exitMessageSelectMode}\n ariaLabel=\"Exit select mode\"\n >\n <i className=\"icon-close\" />\n </Button>\n <span className=\"MessageSelectToolbar-count\" title={formattedMessagesCount}>\n {formattedMessagesCount}\n </span>\n\n {!!selectedMessagesCount && (\n <div className=\"MessageSelectToolbar-actions\">\n {messageListType !== 'scheduled' && (\n <MenuItem\n icon=\"forward\"\n ariaLabel=\"Forward Messages\"\n onClick={openForwardMenuForSelectedMessages}\n >\n <span className=\"item-text\">\n {lang('Forward')}\n </span>\n </MenuItem>\n )}\n <MenuItem\n destructive\n icon=\"delete\"\n onClick={openDeleteModal}\n disabled={!canDeleteMessages}\n ariaLabel={lang('EditAdminGroupDeleteMessages')}\n >\n <span className=\"item-text\">\n {lang('Delete')}\n </span>\n </MenuItem>\n </div>\n )}\n </div>\n <DeleteSelectedMessagesModal\n isOpen={isDeleteModalOpen}\n isSchedule={isSchedule}\n onClose={closeDeleteModal}\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { type: messageListType } = selectCurrentMessageList(global) || {};\n const { canDelete } = selectCanDeleteSelectedMessages(global);\n\n return {\n isSchedule: messageListType === 'scheduled',\n selectedMessagesCount: selectSelectedMessagesCount(global),\n canDeleteMessages: canDelete,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['exitMessageSelectMode', 'openForwardMenuForSelectedMessages']),\n)(MessageSelectToolbar));\n","import React, { FC, memo } from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiUser } from '../../../api/types';\n\nimport useChatContextActions from '../../../hooks/useChatContextActions';\nimport useFlag from '../../../hooks/useFlag';\nimport { isChatPrivate, getPrivateChatUserId } from '../../../modules/helpers';\nimport { selectChat, selectUser, selectIsChatPinned } from '../../../modules/selectors';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport GroupChatInfo from '../../common/GroupChatInfo';\nimport DeleteChatModal from '../../common/DeleteChatModal';\nimport ListItem from '../../ui/ListItem';\n\ntype OwnProps = {\n chatId: number;\n withHandle?: boolean;\n onClick: (id: number) => void;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n privateChatUser?: ApiUser;\n isPinned?: boolean;\n};\n\nconst LeftSearchResultChat: FC<OwnProps & StateProps> = ({\n chatId,\n chat,\n privateChatUser,\n isPinned,\n withHandle,\n onClick,\n}) => {\n const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag();\n\n const contextActions = useChatContextActions({\n chat,\n privateChatUser,\n isPinned,\n handleDelete: openDeleteModal,\n });\n\n if (!chat) {\n return undefined;\n }\n\n return (\n <ListItem\n className=\"chat-item-clickable search-result\"\n onClick={() => onClick(chatId)}\n contextActions={contextActions}\n >\n {isChatPrivate(chatId) ? (\n <PrivateChatInfo userId={chatId} withHandle={withHandle} avatarSize=\"large\" />\n ) : (\n <GroupChatInfo chatId={chatId} withHandle={withHandle} avatarSize=\"large\" />\n )}\n <DeleteChatModal\n isOpen={isDeleteModalOpen}\n onClose={closeDeleteModal}\n chat={chat}\n />\n </ListItem>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const privateChatUserId = chat && getPrivateChatUserId(chat);\n const privateChatUser = privateChatUserId ? selectUser(global, privateChatUserId) : undefined;\n const isPinned = selectIsChatPinned(global, chatId);\n\n return {\n chat,\n privateChatUser,\n isPinned,\n };\n },\n)(LeftSearchResultChat));\n","import React, {\n FC, useEffect, useCallback, useRef, memo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiUser } from '../../../api/types';\n\nimport { getUserFirstOrLastName } from '../../../modules/helpers';\nimport renderText from '../../common/helpers/renderText';\nimport { throttle } from '../../../util/schedulers';\nimport { pick } from '../../../util/iteratees';\nimport useHorizontalScroll from '../../../hooks/useHorizontalScroll';\nimport useLang from '../../../hooks/useLang';\n\nimport Avatar from '../../common/Avatar';\nimport Button from '../../ui/Button';\nimport LeftSearchResultChat from './LeftSearchResultChat';\n\nimport './RecentContacts.scss';\n\ntype OwnProps = {\n onReset: () => void;\n};\n\ntype StateProps = {\n topUserIds?: number[];\n usersById: Record<number, ApiUser>;\n recentlyFoundChatIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'loadTopUsers' | 'loadContactList' | 'openChat' | 'addRecentlyFoundChatId' | 'clearRecentlyFoundChats'\n)>;\n\nconst SEARCH_CLOSE_TIMEOUT_MS = 250;\nconst NBSP = '\\u00A0';\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst RecentContacts: FC<OwnProps & StateProps & DispatchProps> = ({\n topUserIds, usersById, recentlyFoundChatIds,\n onReset, loadTopUsers, loadContactList, openChat,\n addRecentlyFoundChatId, clearRecentlyFoundChats,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const topUsersRef = useRef<HTMLDivElement>(null);\n\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadTopUsers();\n // Loading full contact list for quick local search before user enters the query\n loadContactList();\n });\n }, [loadTopUsers, loadContactList]);\n\n useHorizontalScroll(topUsersRef, !topUserIds);\n\n const handleClick = useCallback(\n (id: number) => {\n openChat({ id });\n onReset();\n setTimeout(() => {\n addRecentlyFoundChatId({ id });\n }, SEARCH_CLOSE_TIMEOUT_MS);\n },\n [openChat, addRecentlyFoundChatId, onReset],\n );\n\n const lang = useLang();\n\n return (\n <div className=\"RecentContacts custom-scroll\">\n {topUserIds && (\n <div className=\"top-peers-section\">\n <div ref={topUsersRef} className=\"top-peers no-selection\">\n {topUserIds.map((userId) => (\n <div className=\"top-peer-item\" onClick={() => handleClick(userId)}>\n <Avatar user={usersById[userId]} />\n <div className=\"top-peer-name\">{renderText(getUserFirstOrLastName(usersById[userId]) || NBSP)}</div>\n </div>\n ))}\n </div>\n </div>\n )}\n {recentlyFoundChatIds && (\n <div className=\"search-section pt-1\">\n <h3 className=\"section-heading mt-0 recent-chats-header\">\n {lang('Recent')}\n\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n ariaLabel=\"Clear recent chats\"\n onClick={clearRecentlyFoundChats}\n >\n <i className=\"icon-close\" />\n </Button>\n </h3>\n {recentlyFoundChatIds.map((id) => (\n <LeftSearchResultChat\n chatId={id}\n onClick={handleClick}\n />\n ))}\n </div>\n )}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { userIds: topUserIds } = global.topPeers;\n const usersById = global.users.byId;\n const { recentlyFoundChatIds } = global.globalSearch;\n\n return {\n topUserIds,\n usersById,\n recentlyFoundChatIds,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadTopUsers',\n 'loadContactList',\n 'openChat',\n 'addRecentlyFoundChatId',\n 'clearRecentlyFoundChats',\n ]),\n)(RecentContacts));\n","import React, {\n FC, memo, useCallback,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport {\n ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus,\n} from '../../../api/types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport {\n getChatTitle,\n getPrivateChatUserId,\n getMessageMediaHash,\n getMessageSummaryText,\n getMessageMediaThumbDataUri,\n getMessageVideo,\n} from '../../../modules/helpers';\nimport { selectChat, selectUser } from '../../../modules/selectors';\nimport renderText from '../../common/helpers/renderText';\nimport { pick } from '../../../util/iteratees';\nimport useMedia from '../../../hooks/useMedia';\nimport { formatPastTimeShort } from '../../../util/dateFormat';\nimport useLang from '../../../hooks/useLang';\n\nimport Avatar from '../../common/Avatar';\nimport VerifiedIcon from '../../common/VerifiedIcon';\nimport ListItem from '../../ui/ListItem';\nimport Link from '../../ui/Link';\n\nimport './ChatMessage.scss';\n\ntype OwnProps = {\n searchQuery?: string;\n message: ApiMessage;\n chatId: number;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n privateChatUser?: ApiUser;\n lastMessageOutgoingStatus?: ApiMessageOutgoingStatus;\n lastSyncTime?: number;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'focusMessage'>;\n\nconst ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({\n message,\n searchQuery,\n chatId,\n chat,\n privateChatUser,\n focusMessage,\n lastSyncTime,\n}) => {\n const mediaThumbnail = getMessageMediaThumbDataUri(message);\n const mediaBlobUrl = useMedia(getMessageMediaHash(message, 'micro'));\n\n const handleClick = useCallback(() => {\n focusMessage({ chatId, messageId: message.id });\n }, [chatId, focusMessage, message.id]);\n\n useLang();\n\n if (!chat) {\n return undefined;\n }\n\n return (\n <ListItem\n className=\"ChatMessage chat-item-clickable\"\n ripple={!IS_MOBILE_SCREEN}\n onClick={handleClick}\n >\n <Avatar\n chat={chat}\n user={privateChatUser}\n withOnlineStatus\n isSavedMessages={privateChatUser && privateChatUser.isSelf}\n lastSyncTime={lastSyncTime}\n />\n <div className=\"info\">\n <div className=\"info-row\">\n <div className=\"title\">\n <h3>{renderText(getChatTitle(chat, privateChatUser))}</h3>\n {chat.isVerified && <VerifiedIcon />}\n </div>\n <div className=\"message-date\">\n <Link className=\"date\">\n {formatPastTimeShort(message.date * 1000)}\n </Link>\n </div>\n\n </div>\n <div className=\"subtitle\">\n <div className=\"message\">\n {renderMessageSummary(message, mediaBlobUrl || mediaThumbnail, searchQuery)}\n </div>\n </div>\n </div>\n </ListItem>\n );\n};\n\nfunction renderMessageSummary(message: ApiMessage, blobUrl?: string, searchQuery?: string) {\n if (!blobUrl) {\n return renderText(getMessageSummaryText(message));\n }\n\n return (\n <span className=\"media-preview\">\n <img src={blobUrl} alt=\"\" />\n {getMessageVideo(message) && <i className=\"icon-play\" />}\n {renderText(getMessageSummaryText(message, true), ['emoji', 'highlight'], { highlight: searchQuery })}\n </span>\n );\n}\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n if (!chat) {\n return {};\n }\n\n const privateChatUserId = getPrivateChatUserId(chat);\n\n return {\n chat,\n ...(privateChatUserId && { privateChatUser: selectUser(global, privateChatUserId) }),\n lastSyncTime: global.lastSyncTime,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'focusMessage',\n ]),\n)(ChatMessage));\n","import React, { FC, memo, useMemo } from '../../../lib/teact/teact';\nimport { formatDateToString } from '../../../util/dateFormat';\n\nimport './DateSuggest.scss';\n\nconst SUGGESTION_COUNT = 8;\n\nexport type OwnProps = {\n searchDate: string;\n onSelect: (value: Date) => void;\n};\n\nconst DateSuggest: FC<OwnProps> = ({\n searchDate, onSelect,\n}) => {\n const suggestions = useMemo(() => getSuggestionsFromDate(searchDate), [searchDate]);\n return (\n <section className=\"DateSuggest custom-scroll custom-scroll-x\">\n {suggestions.map(({ date, text }) => {\n return (\n <div\n onClick={() => onSelect(date)}\n className=\"date-item\"\n key={text}\n >\n <i className=\"icon-calendar\" />\n <span>{text}</span>\n </div>\n );\n })}\n </section>\n );\n};\n\nfunction getSuggestionsFromDate(searchDate: string) {\n const hasYear = searchDate.match(/^\\d{2,4}-\\d{2}-\\d{2}$/g);\n if (hasYear) {\n const date = new Date(searchDate);\n return [{ date, text: formatDateToString(date) }];\n }\n\n const suggestion = [];\n const currentDate = new Date();\n const currentYear = currentDate.getFullYear();\n const latestYear = currentDate.getTime() > (new Date(`${currentYear}-${searchDate}`)).getTime()\n ? currentYear\n : currentYear - 1;\n\n for (let i = 0; i < SUGGESTION_COUNT; i++) {\n const date = new Date(`${latestYear - i}-${searchDate}`);\n suggestion.push({ date, text: formatDateToString(date) });\n }\n\n return suggestion;\n}\n\nexport default memo(DateSuggest);\n","import React, {\n FC, memo, useCallback, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiUser, ApiChat, ApiMessage } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection } from '../../../types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport searchWords from '../../../util/searchWords';\nimport { unique, pick } from '../../../util/iteratees';\nimport { getUserFullName, getMessageSummaryText } from '../../../modules/helpers';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { throttle } from '../../../util/schedulers';\nimport useLang from '../../../hooks/useLang';\n\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport LeftSearchResultChat from './LeftSearchResultChat';\nimport RecentContacts from './RecentContacts';\nimport ChatMessage from './ChatMessage';\nimport DateSuggest from './DateSuggest';\nimport Link from '../../ui/Link';\nimport NothingFound from '../../common/NothingFound';\nimport PickerSelectedItem from '../../common/PickerSelectedItem';\nimport { getTranslation } from '../../../util/langProvider';\n\nexport type OwnProps = {\n searchQuery?: string;\n dateSearchQuery?: string;\n searchDate?: number;\n onReset: () => void;\n onSearchDateSelect: (value: Date) => void;\n};\n\ntype StateProps = {\n currentUserId?: number;\n localContactIds?: number[];\n localChats?: ApiChat[];\n localUsers?: ApiUser[];\n globalChats?: ApiChat[];\n globalUsers?: ApiUser[];\n foundIds?: string[];\n globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>;\n chatsById: Record<number, ApiChat>;\n usersById: Record<number, ApiUser>;\n fetchingStatus?: { chats?: boolean; messages?: boolean };\n lastSyncTime?: number;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'openChat' | 'addRecentlyFoundChatId' | 'searchMessagesGlobal' | 'setGlobalSearchChatId'\n)>;\n\nconst MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH = 4;\nconst LESS_LIST_ITEMS_AMOUNT = 3;\n\nconst sortSearchResults = (a: ApiChat | ApiUser, b: ApiChat | ApiUser) => Number(b.isVerified) - Number(a.isVerified);\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery, searchDate, dateSearchQuery, currentUserId,\n localContactIds, localChats, localUsers, globalChats, globalUsers,\n foundIds, globalMessagesByChatId, chatsById, usersById, fetchingStatus, lastSyncTime,\n onReset, onSearchDateSelect, openChat, addRecentlyFoundChatId, searchMessagesGlobal, setGlobalSearchChatId,\n}) => {\n const [shouldShowMoreLocal, setShouldShowMoreLocal] = useState<boolean>(false);\n const [shouldShowMoreGlobal, setShouldShowMoreGlobal] = useState<boolean>(false);\n\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: 'text',\n query: searchQuery,\n });\n });\n }\n }, [lastSyncTime, searchMessagesGlobal, searchQuery]);\n\n const handleChatClick = useCallback(\n (id: number) => {\n openChat({ id });\n\n if (id !== currentUserId) {\n addRecentlyFoundChatId({ id });\n }\n\n if (!IS_MOBILE_SCREEN) {\n onReset();\n }\n },\n [currentUserId, openChat, addRecentlyFoundChatId, onReset],\n );\n\n const handlePickerItemClick = useCallback((id: number) => {\n setGlobalSearchChatId({ id });\n }, [setGlobalSearchChatId]);\n\n const localResults = useMemo(() => {\n if (!searchQuery || (searchQuery.startsWith('@') && searchQuery.length < 2)) {\n return MEMO_EMPTY_ARRAY;\n }\n\n const foundLocalContacts = localContactIds\n ? localContactIds.filter((id) => {\n const user = usersById[id];\n if (!user) {\n return false;\n }\n\n const fullName = getUserFullName(user);\n return (fullName && searchWords(fullName, searchQuery)) || searchWords(user.username, searchQuery);\n }).map((id) => usersById[id])\n : [];\n\n return unique([\n ...(searchWords(getTranslation('SavedMessages'), searchQuery) ? [currentUserId] : []),\n ...([\n ...foundLocalContacts,\n ...(localChats || []),\n ...(localUsers || []),\n ].sort(sortSearchResults).map((chat) => chat.id)),\n ]) as number[];\n }, [searchQuery, localContactIds, localChats, localUsers, usersById, currentUserId]);\n\n const globalResults = useMemo(() => {\n if (!searchQuery || searchQuery.length < MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH || !globalChats || !globalUsers) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return unique([...globalChats, ...globalUsers].sort(sortSearchResults).map((chat) => chat.id));\n }, [globalChats, globalUsers, searchQuery]);\n\n const foundMessages = useMemo(() => {\n if ((!searchQuery && !searchDate) || !foundIds || foundIds.length === 0) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds\n .map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n\n return (\n globalMessagesByChatId && globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId]\n );\n })\n .filter<ApiMessage>(Boolean as any)\n .sort((a, b) => b.date - a.date);\n }, [foundIds, globalMessagesByChatId, searchQuery, searchDate]);\n\n const handleClickShowMoreLocal = useCallback(() => {\n setShouldShowMoreLocal(!shouldShowMoreLocal);\n }, [shouldShowMoreLocal]);\n\n const handleClickShowMoreGlobal = useCallback(() => {\n setShouldShowMoreGlobal(!shouldShowMoreGlobal);\n }, [shouldShowMoreGlobal]);\n\n const lang = useLang();\n\n function renderFoundMessage(message: ApiMessage) {\n const text = getMessageSummaryText(message);\n const chat = chatsById[message.chatId];\n\n if (!text || !chat) {\n return undefined;\n }\n\n return (\n <ChatMessage\n chatId={message.chatId}\n message={message}\n searchQuery={searchQuery}\n />\n );\n }\n\n const nothingFound = fetchingStatus && !fetchingStatus.chats && !fetchingStatus.messages\n && !localResults.length && !globalResults.length && !foundMessages.length;\n\n if (!searchQuery && !searchDate) {\n return <RecentContacts onReset={onReset} />;\n }\n\n return (\n <InfiniteScroll\n className=\"LeftSearch custom-scroll\"\n items={foundMessages}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {dateSearchQuery && (\n <div className=\"chat-selection no-selection no-scrollbar\">\n <DateSuggest\n searchDate={dateSearchQuery}\n onSelect={onSearchDateSelect}\n />\n </div>\n )}\n {nothingFound && <NothingFound />}\n {!!localResults.length && (\n <div className=\"chat-selection no-selection no-scrollbar\">\n {localResults.map((id) => (\n <PickerSelectedItem\n chatOrUserId={id}\n onClick={handlePickerItemClick}\n clickArg={id}\n />\n ))}\n </div>\n )}\n {!!localResults.length && (\n <div className=\"search-section\">\n <h3 className=\"section-heading\">\n {localResults.length > LESS_LIST_ITEMS_AMOUNT && (\n <Link onClick={handleClickShowMoreLocal}>{shouldShowMoreLocal ? 'Show less' : 'Show more'}</Link>\n )}\n Contacts and Chats\n </h3>\n {localResults.map((id, index) => {\n if (!shouldShowMoreLocal && index >= LESS_LIST_ITEMS_AMOUNT) {\n return undefined;\n }\n\n return (\n <LeftSearchResultChat\n chatId={id}\n onClick={handleChatClick}\n />\n );\n })}\n </div>\n )}\n {!!globalResults.length && (\n <div className=\"search-section\">\n <h3 className=\"section-heading\">\n {globalResults.length > LESS_LIST_ITEMS_AMOUNT && (\n <Link onClick={handleClickShowMoreGlobal}>{shouldShowMoreGlobal ? 'Show less' : 'Show more'}</Link>\n )}\n Global Search\n </h3>\n {globalResults.map((id, index) => {\n if (!shouldShowMoreGlobal && index >= LESS_LIST_ITEMS_AMOUNT) {\n return undefined;\n }\n\n return (\n <LeftSearchResultChat\n chatId={id}\n withHandle\n onClick={handleChatClick}\n />\n );\n })}\n </div>\n )}\n {!!foundMessages.length && (\n <div className=\"search-section\">\n <h3 className=\"section-heading\">{lang('SearchMessages')}</h3>\n {foundMessages.map(renderFoundMessage)}\n </div>\n )}\n </InfiniteScroll>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { byId: chatsById } = global.chats;\n const { byId: usersById } = global.users;\n\n const { userIds: localContactIds } = global.contactList || {};\n\n if (!localContactIds) {\n return {\n chatsById,\n usersById,\n };\n }\n\n const { currentUserId, messages, lastSyncTime } = global;\n const {\n fetchingStatus, globalResults, localResults, resultsByType,\n } = global.globalSearch;\n const {\n chats: globalChats,\n users: globalUsers,\n } = globalResults || {};\n const { chats: localChats, users: localUsers } = localResults || {};\n const { byChatId: globalMessagesByChatId } = messages;\n const { foundIds } = (resultsByType && resultsByType.text) || {};\n\n return {\n currentUserId,\n localContactIds,\n localChats,\n localUsers,\n globalChats,\n globalUsers,\n foundIds,\n globalMessagesByChatId,\n chatsById,\n usersById,\n fetchingStatus,\n lastSyncTime,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'openChat',\n 'addRecentlyFoundChatId',\n 'searchMessagesGlobal',\n 'setGlobalSearchChatId',\n ]),\n)(ChatResults));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiMessage } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport { getMessageSummaryText } from '../../../modules/helpers';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { throttle } from '../../../util/schedulers';\n\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport ChatMessage from './ChatMessage';\nimport NothingFound from '../../common/NothingFound';\nimport DateSuggest from './DateSuggest';\n\nexport type OwnProps = {\n searchQuery?: string;\n dateSearchQuery?: string;\n onReset: () => void;\n onSearchDateSelect: (value: Date) => void;\n};\n\ntype StateProps = {\n currentUserId?: number;\n foundIds?: string[];\n globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>;\n chatsById: Record<number, ApiChat>;\n fetchingStatus?: { chats?: boolean; messages?: boolean };\n lastSyncTime?: number;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal')>;\n\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst ChatMessageResults: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery,\n currentUserId,\n dateSearchQuery,\n foundIds,\n globalMessagesByChatId,\n chatsById,\n fetchingStatus,\n lastSyncTime,\n searchMessagesGlobal,\n onSearchDateSelect,\n}) => {\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: 'text',\n query: searchQuery,\n chatId: currentUserId,\n });\n });\n }\n }, [currentUserId, lastSyncTime, searchMessagesGlobal, searchQuery]);\n\n const foundMessages = useMemo(() => {\n if (!foundIds || foundIds.length === 0) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds\n .map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n\n return (\n globalMessagesByChatId && globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId]\n );\n })\n .filter<ApiMessage>(Boolean as any)\n .sort((a, b) => b.date - a.date);\n }, [foundIds, globalMessagesByChatId]);\n\n function renderFoundMessage(message: ApiMessage) {\n const text = getMessageSummaryText(message);\n const chat = chatsById[message.chatId];\n\n if (!text || !chat) {\n return undefined;\n }\n\n return (\n <ChatMessage\n chatId={message.chatId}\n message={message}\n searchQuery={searchQuery}\n />\n );\n }\n\n const nothingFound = fetchingStatus && !fetchingStatus.chats && !fetchingStatus.messages && !foundMessages.length;\n\n return (\n <div className=\"LeftSearch\">\n <InfiniteScroll\n className=\"search-content custom-scroll chat-list\"\n items={foundMessages}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {dateSearchQuery && (\n <div className=\"chat-selection no-selection no-scrollbar\">\n <DateSuggest\n searchDate={dateSearchQuery}\n onSelect={onSearchDateSelect}\n />\n </div>\n )}\n {nothingFound && <NothingFound />}\n {!!foundMessages.length && foundMessages.map(renderFoundMessage)}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { byId: chatsById } = global.chats;\n const { currentUserId, messages: { byChatId: globalMessagesByChatId }, lastSyncTime } = global;\n const { fetchingStatus, resultsByType } = global.globalSearch;\n\n const { foundIds } = (resultsByType && resultsByType.text) || {};\n\n return {\n currentUserId,\n foundIds,\n globalMessagesByChatId,\n chatsById,\n fetchingStatus,\n lastSyncTime,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['searchMessagesGlobal']),\n)(ChatMessageResults));\n","import { GlobalState } from '../../../../global/types';\nimport {\n ApiChat, ApiGlobalMessageSearchType, ApiMessage, ApiUser,\n} from '../../../../api/types';\n\nexport type StateProps = {\n isLoading?: boolean;\n chatsById: Record<number, ApiChat>;\n usersById: Record<number, ApiUser>;\n globalMessagesByChatId?: Record<number, { byId: Record<number, ApiMessage> }>;\n foundIds?: string[];\n lastSyncTime?: number;\n searchChatId?: number;\n};\n\nexport function createMapStateToProps(type: ApiGlobalMessageSearchType) {\n return (global: GlobalState, props: any) => {\n const { byId: chatsById } = global.chats;\n const { byId: usersById } = global.users;\n const {\n fetchingStatus, resultsByType, chatId,\n } = global.globalSearch;\n\n // One component is used for two different types of results.\n // The differences between them are only in the isVoice property.\n // The rest of the search results use their own personal components.\n const currentType = type !== 'audio' ? type : (props && props.isVoice ? 'voice' : 'audio');\n\n const { byChatId: globalMessagesByChatId } = global.messages;\n const { foundIds } = (resultsByType && resultsByType[currentType]) || {};\n\n return {\n isLoading: foundIds === undefined\n || (fetchingStatus ? Boolean(fetchingStatus.chats || fetchingStatus.messages) : false),\n chatsById,\n usersById,\n globalMessagesByChatId,\n foundIds,\n searchChatId: chatId,\n lastSyncTime: global.lastSyncTime,\n };\n };\n}\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection, MediaViewerOrigin } from '../../../types';\n\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';\nimport { pick } from '../../../util/iteratees';\nimport buildClassName from '../../../util/buildClassName';\nimport { throttle } from '../../../util/schedulers';\n\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport Media from '../../common/Media';\nimport ChatMessage from './ChatMessage';\nimport NothingFound from '../../common/NothingFound';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\nimport { SLIDE_TRANSITION_DURATION } from '../../../config';\nimport Loading from '../../ui/Loading';\n\nexport type OwnProps = {\n searchQuery?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'openMediaViewer')>;\n\nconst CURRENT_TYPE = 'media';\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst MediaResults: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery,\n searchChatId,\n isLoading,\n globalMessagesByChatId,\n foundIds,\n lastSyncTime,\n searchMessagesGlobal,\n openMediaViewer,\n}) => {\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: CURRENT_TYPE,\n query: searchQuery,\n chatId: searchChatId,\n });\n });\n }\n }, [lastSyncTime, searchMessagesGlobal, searchQuery, searchChatId]);\n\n const foundMessages = useMemo(() => {\n if (!foundIds || !globalMessagesByChatId) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds.map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n\n return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];\n }).filter(Boolean);\n }, [globalMessagesByChatId, foundIds]);\n\n const handleSelectMedia = useCallback((messageId: number, chatId: number) => {\n openMediaViewer({\n chatId,\n messageId,\n origin: MediaViewerOrigin.SearchResult,\n });\n }, [openMediaViewer]);\n\n function renderGallery() {\n return (\n <div className=\"media-list\">\n {foundMessages.map((message) => (\n <Media\n key={message.id}\n idPrefix=\"search-media\"\n message={message}\n onClick={handleSelectMedia}\n />\n ))}\n </div>\n );\n }\n\n function renderSearchResult() {\n return foundMessages.map((message) => (\n <ChatMessage\n key={message.id}\n chatId={message.chatId}\n message={message}\n />\n ));\n }\n\n const canRenderContents = useAsyncRendering([searchQuery], SLIDE_TRANSITION_DURATION) && !isLoading;\n const isMediaGrid = canRenderContents && foundIds && foundIds.length > 0 && !searchQuery;\n const isMessageList = canRenderContents && foundIds && foundIds.length > 0 && searchQuery;\n\n const classNames = buildClassName(\n 'search-content custom-scroll',\n isMessageList && 'chat-list',\n );\n\n return (\n <div className=\"LeftSearch\">\n <InfiniteScroll\n className={classNames}\n items={foundMessages}\n itemSelector={!searchQuery ? '.Media' : '.ListItem'}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {!canRenderContents && <Loading />}\n {canRenderContents && (!foundIds || foundIds.length === 0) && <NothingFound />}\n {isMediaGrid && renderGallery()}\n {isMessageList && renderSearchResult()}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n createMapStateToProps(CURRENT_TYPE),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'searchMessagesGlobal',\n 'openMediaViewer',\n ]),\n)(MediaResults));\n","import { ApiChat, ApiMessage, ApiUser } from '../../../../api/types';\nimport {\n getChatTitle,\n getSenderTitle,\n isChatPrivate,\n isChatGroup,\n} from '../../../../modules/helpers';\n\nexport function getSenderName(\n message: ApiMessage, chatsById: Record<number, ApiChat>, usersById: Record<number, ApiUser>,\n) {\n const { senderId } = message;\n if (!senderId) {\n return undefined;\n }\n\n const sender = isChatPrivate(senderId) ? usersById[senderId] : chatsById[senderId];\n\n let senderName = getSenderTitle(sender);\n\n const chat = chatsById[message.chatId];\n if (chat) {\n if (isChatPrivate(senderId) && (sender as ApiUser).isSelf) {\n senderName = `You → ${getChatTitle(chat)}`;\n } else if (isChatGroup(chat)) {\n senderName += ` → ${getChatTitle(chat)}`;\n }\n }\n\n return senderName;\n}\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection } from '../../../types';\n\nimport { SLIDE_TRANSITION_DURATION } from '../../../config';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';\nimport { pick } from '../../../util/iteratees';\nimport { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';\nimport { getSenderName } from './helpers/getSenderName';\nimport { throttle } from '../../../util/schedulers';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\n\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport WebLink from '../../common/WebLink';\nimport NothingFound from '../../common/NothingFound';\nimport Loading from '../../ui/Loading';\n\nexport type OwnProps = {\n searchQuery?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage')>;\n\nconst CURRENT_TYPE = 'links';\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery,\n searchChatId,\n isLoading,\n chatsById,\n usersById,\n globalMessagesByChatId,\n foundIds,\n lastSyncTime,\n searchMessagesGlobal,\n focusMessage,\n}) => {\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: CURRENT_TYPE,\n query: searchQuery,\n chatId: searchChatId,\n });\n });\n }\n }, [lastSyncTime, searchMessagesGlobal, searchQuery, searchChatId]);\n\n const foundMessages = useMemo(() => {\n if (!foundIds || !globalMessagesByChatId) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds.map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n\n return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];\n }).filter(Boolean);\n }, [globalMessagesByChatId, foundIds]);\n\n const handleMessageFocus = useCallback((messageId: number, chatId: number) => {\n focusMessage({ chatId, messageId });\n }, [focusMessage]);\n\n function renderList() {\n return foundMessages.map((message, index) => {\n const shouldDrawDateDivider = index === 0\n || toYearMonth(message.date) !== toYearMonth(foundMessages[index - 1].date);\n return (\n <div\n className=\"ListItem\"\n key={message.id}\n >\n {shouldDrawDateDivider && (\n <p className=\"section-heading\">{formatMonthAndYear(new Date(message.date * 1000))}</p>\n )}\n <WebLink\n key={message.id}\n message={message}\n senderTitle={getSenderName(message, chatsById, usersById)}\n onMessageClick={handleMessageFocus}\n />\n </div>\n );\n });\n }\n\n const canRenderContents = useAsyncRendering([searchQuery], SLIDE_TRANSITION_DURATION) && !isLoading;\n\n return (\n <div className=\"LeftSearch\">\n <InfiniteScroll\n className=\"search-content documents-list custom-scroll\"\n items={foundMessages}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {!canRenderContents && <Loading />}\n {canRenderContents && (!foundIds || foundIds.length === 0) && <NothingFound />}\n {canRenderContents && foundIds && foundIds.length > 0 && renderList()}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n createMapStateToProps(CURRENT_TYPE),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'searchMessagesGlobal',\n 'focusMessage',\n ]),\n)(LinkResults));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiMessage } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection } from '../../../types';\n\nimport { SLIDE_TRANSITION_DURATION } from '../../../config';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';\nimport { pick } from '../../../util/iteratees';\nimport { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';\nimport { getSenderName } from './helpers/getSenderName';\nimport { throttle } from '../../../util/schedulers';\nimport { getMessageDocument } from '../../../modules/helpers';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\n\nimport Document from '../../common/Document';\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport NothingFound from '../../common/NothingFound';\nimport Loading from '../../ui/Loading';\n\nexport type OwnProps = {\n searchQuery?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage')>;\n\nconst CURRENT_TYPE = 'documents';\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst FileResults: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery,\n searchChatId,\n isLoading,\n chatsById,\n usersById,\n globalMessagesByChatId,\n foundIds,\n lastSyncTime,\n searchMessagesGlobal,\n focusMessage,\n}) => {\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: CURRENT_TYPE,\n query: searchQuery,\n chatId: searchChatId,\n });\n });\n }\n }, [lastSyncTime, searchMessagesGlobal, searchQuery, searchChatId]);\n\n const foundMessages = useMemo(() => {\n if (!foundIds || !globalMessagesByChatId) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds.map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n const message = globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];\n\n return message && getMessageDocument(message) ? message : undefined;\n }).filter(Boolean) as ApiMessage[];\n }, [globalMessagesByChatId, foundIds]);\n\n const handleMessageFocus = useCallback((messageId: number, chatId: number) => {\n focusMessage({ chatId, messageId });\n }, [focusMessage]);\n\n function renderList() {\n return foundMessages.map((message, index) => {\n const shouldDrawDateDivider = index === 0\n || toYearMonth(message.date) !== toYearMonth(foundMessages[index - 1].date);\n return (\n <div\n className=\"ListItem\"\n key={message.id}\n >\n {shouldDrawDateDivider && (\n <p className=\"section-heading\">{formatMonthAndYear(new Date(message.date * 1000))}</p>\n )}\n <Document\n message={message}\n withDate\n datetime={message.date}\n smaller\n sender={getSenderName(message, chatsById, usersById)}\n className=\"scroll-item\"\n onDateClick={handleMessageFocus}\n />\n </div>\n );\n });\n }\n\n const canRenderContents = useAsyncRendering([searchQuery], SLIDE_TRANSITION_DURATION) && !isLoading;\n\n return (\n <div className=\"LeftSearch\">\n <InfiniteScroll\n className=\"search-content documents-list custom-scroll\"\n items={foundMessages}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {!canRenderContents && <Loading />}\n {canRenderContents && (!foundIds || foundIds.length === 0) && <NothingFound />}\n {canRenderContents && foundIds && foundIds.length > 0 && renderList()}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n createMapStateToProps(CURRENT_TYPE),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'searchMessagesGlobal',\n 'focusMessage',\n ]),\n)(FileResults));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { LoadMoreDirection } from '../../../types';\n\nimport { SLIDE_TRANSITION_DURATION } from '../../../config';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';\nimport { pick } from '../../../util/iteratees';\nimport { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';\nimport { getSenderName } from './helpers/getSenderName';\nimport { throttle } from '../../../util/schedulers';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\n\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport Audio from '../../common/Audio';\nimport NothingFound from '../../common/NothingFound';\nimport Loading from '../../ui/Loading';\n\nexport type OwnProps = {\n isVoice?: boolean;\n searchQuery?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage' | 'openAudioPlayer')>;\n\nconst runThrottled = throttle((cb) => cb(), 500, true);\n\nconst AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({\n isVoice,\n searchQuery,\n searchChatId,\n isLoading,\n chatsById,\n usersById,\n globalMessagesByChatId,\n foundIds,\n lastSyncTime,\n searchMessagesGlobal,\n focusMessage,\n openAudioPlayer,\n}) => {\n const currentType = isVoice ? 'voice' : 'audio';\n const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {\n if (lastSyncTime && direction === LoadMoreDirection.Backwards) {\n runThrottled(() => {\n searchMessagesGlobal({\n type: currentType,\n query: searchQuery,\n chatId: searchChatId,\n });\n });\n }\n }, [currentType, lastSyncTime, searchMessagesGlobal, searchQuery, searchChatId]);\n\n const foundMessages = useMemo(() => {\n if (!foundIds || !globalMessagesByChatId) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return foundIds.map((id) => {\n const [chatId, messageId] = id.split('_').map(Number);\n\n return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];\n }).filter(Boolean);\n }, [globalMessagesByChatId, foundIds]);\n\n const handleMessageFocus = useCallback((messageId: number, chatId: number) => {\n focusMessage({ chatId, messageId });\n }, [focusMessage]);\n\n const handlePlayAudio = useCallback((messageId: number, chatId: number) => {\n openAudioPlayer({ chatId, messageId });\n }, [openAudioPlayer]);\n\n function renderList() {\n return foundMessages.map((message, index) => {\n const shouldDrawDateDivider = index === 0\n || toYearMonth(message.date) !== toYearMonth(foundMessages[index - 1].date);\n return (\n <div\n className=\"ListItem\"\n key={message.id}\n >\n {shouldDrawDateDivider && (\n <p className=\"section-heading\">{formatMonthAndYear(new Date(message.date * 1000))}</p>\n )}\n <Audio\n key={message.id}\n message={message}\n renderingFor=\"searchResult\"\n senderTitle={getSenderName(message, chatsById, usersById)}\n date={message.date}\n lastSyncTime={lastSyncTime}\n className=\"scroll-item\"\n onPlay={handlePlayAudio}\n onDateClick={handleMessageFocus}\n />\n </div>\n );\n });\n }\n\n const canRenderContents = useAsyncRendering([searchQuery], SLIDE_TRANSITION_DURATION) && !isLoading;\n\n return (\n <div className=\"LeftSearch\">\n <InfiniteScroll\n className=\"search-content documents-list custom-scroll\"\n items={foundMessages}\n onLoadMore={handleLoadMore}\n noFastList\n >\n {!canRenderContents && <Loading />}\n {canRenderContents && (!foundIds || foundIds.length === 0) && <NothingFound />}\n {canRenderContents && foundIds && foundIds.length > 0 && renderList()}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n createMapStateToProps('audio'),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'searchMessagesGlobal',\n 'focusMessage',\n 'openAudioPlayer',\n ]),\n)(AudioResults));\n","import React, {\n FC, memo, useCallback, useState, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { GlobalSearchContent } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport { parseDateString } from '../../../util/dateFormat';\n\nimport TabList from '../../ui/TabList';\nimport Transition from '../../ui/Transition';\nimport ChatResults from './ChatResults';\nimport UserChatResults from './ChatMessageResults';\nimport MediaResults from './MediaResults';\nimport LinkResults from './LinkResults';\nimport FileResults from './FileResults';\nimport AudioResults from './AudioResults';\n\nimport './LeftSearch.scss';\n\nexport type OwnProps = {\n searchQuery?: string;\n searchDate?: number;\n onReset: () => void;\n};\n\ntype StateProps = {\n currentContent?: GlobalSearchContent;\n chatId?: number;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('setGlobalSearchContent' | 'setGlobalSearchDate')>;\n\nconst TABS = [\n { type: GlobalSearchContent.ChatList, title: 'SearchAllChatsShort' },\n { type: GlobalSearchContent.Media, title: 'SharedMediaTab2' },\n { type: GlobalSearchContent.Links, title: 'SharedLinksTab2' },\n { type: GlobalSearchContent.Files, title: 'SharedFilesTab2' },\n { type: GlobalSearchContent.Music, title: 'SharedMusicTab2' },\n { type: GlobalSearchContent.Voice, title: 'SharedVoiceTab2' },\n];\n\nconst CHAT_TABS = [\n { type: GlobalSearchContent.ChatList, title: 'All Messages' },\n ...TABS.slice(1),\n];\n\nconst TRANSITION_RENDER_COUNT = Object.keys(GlobalSearchContent).length / 2;\n\nconst LeftSearch: FC<OwnProps & StateProps & DispatchProps> = ({\n searchQuery,\n searchDate,\n currentContent = GlobalSearchContent.ChatList,\n chatId,\n setGlobalSearchContent,\n setGlobalSearchDate,\n onReset,\n}) => {\n const [activeTab, setActiveTab] = useState(0);\n const dateSearchQuery = useMemo(() => parseDateString(searchQuery), [searchQuery]);\n\n const handleSwitchTab = useCallback((index: number) => {\n const tab = TABS[index];\n setGlobalSearchContent({ content: tab.type });\n setActiveTab(index);\n }, [setGlobalSearchContent]);\n\n const handleSearchDateSelect = useCallback((value: Date) => {\n setGlobalSearchDate({ date: value.getTime() / 1000 });\n }, [setGlobalSearchDate]);\n\n return (\n <div className=\"LeftSearch\">\n <TabList activeTab={activeTab} tabs={chatId ? CHAT_TABS : TABS} onSwitchTab={handleSwitchTab} />\n <Transition name=\"slide\" renderCount={TRANSITION_RENDER_COUNT} activeKey={currentContent}>\n {() => {\n switch (currentContent) {\n case GlobalSearchContent.ChatList:\n if (chatId) {\n return (\n <UserChatResults\n searchQuery={searchQuery}\n dateSearchQuery={dateSearchQuery}\n onReset={onReset}\n onSearchDateSelect={handleSearchDateSelect}\n />\n );\n }\n return (\n <ChatResults\n searchQuery={searchQuery}\n searchDate={searchDate}\n dateSearchQuery={dateSearchQuery}\n onReset={onReset}\n onSearchDateSelect={handleSearchDateSelect}\n />\n );\n case GlobalSearchContent.Media:\n return <MediaResults searchQuery={searchQuery} />;\n case GlobalSearchContent.Links:\n return <LinkResults searchQuery={searchQuery} />;\n case GlobalSearchContent.Files:\n return <FileResults searchQuery={searchQuery} />;\n case GlobalSearchContent.Music:\n return (\n <AudioResults\n key=\"audio\"\n searchQuery={searchQuery}\n />\n );\n case GlobalSearchContent.Voice:\n return (\n <AudioResults\n key=\"voice\"\n isVoice\n searchQuery={searchQuery}\n />\n );\n default:\n return undefined;\n }\n }}\n </Transition>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { currentContent, chatId } = global.globalSearch;\n\n return { currentContent, chatId };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['setGlobalSearchContent', 'setGlobalSearchDate']),\n)(LeftSearch));\n","import { useState, useCallback, useRef } from '../lib/teact/teact';\n\nexport type ReducerAction<Actions> = { type: Actions; payload?: any };\nexport type StateReducer<State, Actions> = (state: State, action: ReducerAction<Actions>) => State;\nexport type Dispatch<Actions> = (action: ReducerAction<Actions>) => void;\n\nexport default function useReducer<State, Actions>(\n reducer: StateReducer<State, Actions>,\n initialState: State,\n) {\n const reducerRef = useRef(reducer);\n const [state, setState] = useState<State>(initialState);\n\n const dispatch = useCallback((action: ReducerAction<Actions>) => {\n setState((currentState) => reducerRef.current(currentState, action));\n }, []);\n\n return [\n state,\n dispatch,\n ] as [State, Dispatch<Actions>];\n}\n","import useReducer, { StateReducer, Dispatch } from '../useReducer';\nimport { ApiChatFolder } from '../../api/types';\nimport { pick, omit } from '../../util/iteratees';\n\nexport type FolderChatType = {\n icon: string;\n title: string;\n key: keyof Pick<ApiChatFolder, (\n 'contacts' | 'nonContacts' | 'groups' | 'channels' | 'bots' |\n 'excludeMuted' | 'excludeArchived' | 'excludeRead'\n )>;\n};\n\nexport const INCLUDED_CHAT_TYPES: FolderChatType[] = [\n { icon: 'user', title: 'FilterContacts', key: 'contacts' },\n { icon: 'non-contacts', title: 'FilterNonContacts', key: 'nonContacts' },\n { icon: 'group', title: 'FilterGroups', key: 'groups' },\n { icon: 'channel', title: 'FilterChannels', key: 'channels' },\n { icon: 'bots', title: 'FilterBots', key: 'bots' },\n];\n\nexport const EXCLUDED_CHAT_TYPES: FolderChatType[] = [\n { icon: 'mute', title: 'FilterMuted', key: 'excludeMuted' },\n { icon: 'archive', title: 'FilterArchived', key: 'excludeArchived' },\n { icon: 'readchats', title: 'FilterRead', key: 'excludeRead' },\n];\n\nconst INCLUDE_FILTER_FIELDS: Array<keyof FolderIncludeFilters> = [\n 'includedChatIds', 'bots', 'channels', 'groups', 'contacts', 'nonContacts',\n];\nconst EXCLUDE_FILTER_FIELDS: Array<keyof FolderExcludeFilters> = [\n 'excludedChatIds', 'excludeArchived', 'excludeMuted', 'excludeRead',\n];\n\nexport function selectChatFilters(state: FoldersState, mode: 'included' | 'excluded', selectTemp?: boolean) {\n let selectedChatIds: number[] = [];\n let selectedChatTypes: FolderChatType['key'][] = [];\n\n if (mode === 'included') {\n const {\n includedChatIds,\n ...includeFilters\n } = selectTemp\n ? state.includeFilters || {}\n : pick(\n state.folder,\n INCLUDE_FILTER_FIELDS,\n );\n\n selectedChatIds = includedChatIds || [];\n selectedChatTypes = (Object.keys(includeFilters) as Array<keyof typeof includeFilters>)\n .filter((key) => Boolean(includeFilters[key]));\n } else {\n const {\n excludedChatIds,\n ...excludeFilters\n } = selectTemp\n ? state.excludeFilters || {}\n : pick(\n state.folder,\n EXCLUDE_FILTER_FIELDS,\n );\n\n selectedChatIds = excludedChatIds || [];\n selectedChatTypes = (Object.keys(excludeFilters) as Array<keyof typeof excludeFilters>)\n .filter((key) => Boolean(excludeFilters[key]));\n }\n\n return {\n selectedChatIds,\n selectedChatTypes,\n };\n}\n\nfunction getSuggestedFolderName(includeFilters?: FolderIncludeFilters) {\n if (includeFilters) {\n const {\n includedChatIds,\n ...filters\n } = includeFilters;\n\n if (\n Object.values(filters).filter(Boolean).length > 1\n || (includedChatIds && includedChatIds.length)\n ) {\n return '';\n }\n\n if (filters.bots) {\n return 'Bots';\n } else if (filters.groups) {\n return 'Groups';\n } else if (filters.channels) {\n return 'Channels';\n } else if (filters.contacts) {\n return 'Contacts';\n } else if (filters.nonContacts) {\n return 'Non-Contacts';\n }\n }\n\n return '';\n}\n\ntype FolderIncludeFilters = Pick<ApiChatFolder, (\n 'includedChatIds' | 'bots' | 'channels' | 'groups' | 'contacts' | 'nonContacts'\n)>;\ntype FolderExcludeFilters = Pick<ApiChatFolder, 'excludedChatIds' | 'excludeArchived' | 'excludeMuted' | 'excludeRead'>;\n\nexport type FoldersState = {\n mode: 'create' | 'edit';\n isLoading?: boolean;\n isTouched?: boolean;\n error?: string;\n folderId?: number;\n chatFilter: string;\n folder: Omit<ApiChatFolder, 'id' | 'description' | 'emoticon'>;\n includeFilters?: FolderIncludeFilters;\n excludeFilters?: FolderExcludeFilters;\n};\nexport type FoldersActions = (\n 'setTitle' | 'saveFilters' | 'editFolder' | 'reset' | 'setChatFilter' | 'setIsLoading' | 'setError' |\n 'editIncludeFilters' | 'editExcludeFilters' | 'setIncludeFilters' | 'setExcludeFilters'\n);\nexport type FolderEditDispatch = Dispatch<FoldersActions>;\n\nconst INITIAL_STATE: FoldersState = {\n mode: 'create',\n chatFilter: '',\n folder: {\n title: '',\n includedChatIds: [],\n excludedChatIds: [],\n },\n};\n\nconst foldersReducer: StateReducer<FoldersState, FoldersActions> = (\n state,\n action,\n) => {\n switch (action.type) {\n case 'setTitle':\n return {\n ...state,\n folder: {\n ...state.folder,\n title: action.payload,\n },\n isTouched: true,\n };\n case 'editIncludeFilters':\n return {\n ...state,\n includeFilters: pick(\n state.folder,\n INCLUDE_FILTER_FIELDS,\n ),\n };\n case 'editExcludeFilters':\n return {\n ...state,\n excludeFilters: pick(\n state.folder,\n EXCLUDE_FILTER_FIELDS,\n ),\n };\n case 'setIncludeFilters':\n return {\n ...state,\n includeFilters: action.payload,\n chatFilter: '',\n };\n case 'setExcludeFilters':\n return {\n ...state,\n excludeFilters: action.payload,\n chatFilter: '',\n };\n case 'saveFilters':\n if (state.includeFilters) {\n return {\n ...state,\n folder: {\n ...omit(state.folder, INCLUDE_FILTER_FIELDS),\n title: state.folder.title ? state.folder.title : getSuggestedFolderName(state.includeFilters),\n ...state.includeFilters,\n },\n includeFilters: undefined,\n chatFilter: '',\n isTouched: true,\n };\n } else if (state.excludeFilters) {\n return {\n ...state,\n folder: {\n ...omit(state.folder, EXCLUDE_FILTER_FIELDS),\n ...state.excludeFilters,\n },\n excludeFilters: undefined,\n chatFilter: '',\n isTouched: true,\n };\n } else {\n return state;\n }\n case 'editFolder': {\n const { id: folderId, description, ...folder } = action.payload;\n\n return {\n mode: 'edit',\n folderId,\n folder,\n chatFilter: '',\n };\n }\n case 'setChatFilter': {\n return {\n ...state,\n chatFilter: action.payload,\n };\n }\n case 'setIsLoading': {\n return {\n ...state,\n isLoading: action.payload,\n };\n }\n case 'setError': {\n return {\n ...state,\n error: action.payload,\n };\n }\n case 'reset':\n return INITIAL_STATE;\n default:\n return state;\n }\n};\n\nexport default () => {\n return useReducer(foldersReducer, INITIAL_STATE);\n};\n","import useReducer, { StateReducer, Dispatch } from '../useReducer';\n\nexport type TwoFaActions = (\n 'setCurrentPassword' | 'setPassword' | 'setHint' | 'setEmail' | 'reset'\n);\nexport type TwoFaDispatch = Dispatch<TwoFaActions>;\n\nexport type TwoFaState = {\n currentPassword: string;\n password: string;\n hint: string;\n email: string;\n};\n\nconst INITIAL_STATE: TwoFaState = {\n currentPassword: '',\n password: '',\n hint: '',\n email: '',\n};\n\nconst twoFaReducer: StateReducer<TwoFaState, TwoFaActions> = (\n state,\n action,\n) => {\n switch (action.type) {\n case 'setCurrentPassword':\n return {\n ...state,\n currentPassword: action.payload,\n };\n\n case 'setPassword':\n return {\n ...state,\n password: action.payload,\n };\n\n case 'setHint':\n return {\n ...state,\n hint: action.payload,\n };\n\n case 'setEmail':\n return {\n ...state,\n email: action.payload,\n };\n\n case 'reset':\n return INITIAL_STATE;\n\n default:\n return state;\n }\n};\n\nexport default () => {\n return useReducer(twoFaReducer, INITIAL_STATE);\n};\n","import React, {\n FC, useCallback, useMemo, memo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { SettingsScreens } from '../../../types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\n\nimport DropdownMenu from '../../ui/DropdownMenu';\nimport MenuItem from '../../ui/MenuItem';\nimport Button from '../../ui/Button';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\ntype OwnProps = {\n currentScreen: SettingsScreens;\n editedFolderId?: number;\n onReset: () => void;\n onSaveFilter: () => void;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'signOut' | 'deleteChatFolder'>;\n\nconst SettingsHeader: FC<OwnProps & DispatchProps> = ({\n currentScreen,\n editedFolderId,\n onReset,\n onSaveFilter,\n signOut,\n deleteChatFolder,\n}) => {\n const [isSignOutDialogOpen, setIsSignOutDialogOpen] = useState(false);\n const [isDeleteFolderDialogOpen, setIsDeleteFolderDialogOpen] = useState(false);\n\n const openSignOutConfirmation = useCallback(() => {\n setIsSignOutDialogOpen(true);\n }, []);\n\n const closeSignOutConfirmation = useCallback(() => {\n setIsSignOutDialogOpen(false);\n }, []);\n\n const openDeleteFolderConfirmation = useCallback(() => {\n setIsDeleteFolderDialogOpen(true);\n }, []);\n\n const closeDeleteFolderConfirmation = useCallback(() => {\n setIsDeleteFolderDialogOpen(false);\n }, []);\n\n const handleSignOutMessage = useCallback(() => {\n closeSignOutConfirmation();\n signOut();\n }, [closeSignOutConfirmation, signOut]);\n\n const handleDeleteFolderMessage = useCallback(() => {\n closeDeleteFolderConfirmation();\n deleteChatFolder({ id: editedFolderId });\n onReset();\n }, [editedFolderId, closeDeleteFolderConfirmation, deleteChatFolder, onReset]);\n\n const SettingsMenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {\n return ({ onTrigger, isOpen }) => (\n <Button\n round\n ripple={!IS_MOBILE_SCREEN}\n size=\"smaller\"\n color=\"translucent\"\n className={isOpen ? 'active' : ''}\n onClick={onTrigger}\n ariaLabel=\"More actions\"\n >\n <i className=\"icon-more\" />\n </Button>\n );\n }, []);\n\n const lang = useLang();\n\n function renderHeaderContent() {\n switch (currentScreen) {\n case SettingsScreens.EditProfile:\n return <h3>{lang('EditProfile')}</h3>;\n case SettingsScreens.General:\n return <h3>{lang('General')}</h3>;\n case SettingsScreens.Notifications:\n return <h3>{lang('Notifications')}</h3>;\n case SettingsScreens.Privacy:\n return <h3>{lang('PrivacySettings')}</h3>;\n case SettingsScreens.Language:\n return <h3>{lang('Language')}</h3>;\n\n case SettingsScreens.GeneralChatBackground:\n return <h3>{lang('ChatBackground')}</h3>;\n case SettingsScreens.GeneralChatBackgroundColor:\n return <h3>{lang('SetColor')}</h3>;\n\n case SettingsScreens.PrivacyPhoneNumber:\n return <h3>{lang('PrivacyPhone')}</h3>;\n case SettingsScreens.PrivacyLastSeen:\n return <h3>{lang('PrivacyLastSeen')}</h3>;\n case SettingsScreens.PrivacyProfilePhoto:\n return <h3>{lang('Privacy.ProfilePhoto')}</h3>;\n case SettingsScreens.PrivacyForwarding:\n return <h3>{lang('PrivacyForwards')}</h3>;\n case SettingsScreens.PrivacyGroupChats:\n return <h3>{lang('AutodownloadGroupChats')}</h3>;\n case SettingsScreens.PrivacyPhoneNumberAllowedContacts:\n case SettingsScreens.PrivacyLastSeenAllowedContacts:\n case SettingsScreens.PrivacyProfilePhotoAllowedContacts:\n case SettingsScreens.PrivacyForwardingAllowedContacts:\n case SettingsScreens.PrivacyGroupChatsAllowedContacts:\n return <h3>{lang('AlwaysShareWith')}</h3>;\n case SettingsScreens.PrivacyPhoneNumberDeniedContacts:\n case SettingsScreens.PrivacyLastSeenDeniedContacts:\n case SettingsScreens.PrivacyProfilePhotoDeniedContacts:\n case SettingsScreens.PrivacyForwardingDeniedContacts:\n case SettingsScreens.PrivacyGroupChatsDeniedContacts:\n return <h3>{lang('NeverShareWith')}</h3>;\n\n case SettingsScreens.PrivacyActiveSessions:\n return <h3>{lang('SessionsTitle')}</h3>;\n case SettingsScreens.PrivacyBlockedUsers:\n return <h3>{lang('BlockedUsers')}</h3>;\n\n case SettingsScreens.TwoFaDisabled:\n case SettingsScreens.TwoFaEnabled:\n return <h3>{lang('TwoStepVerification')}</h3>;\n case SettingsScreens.TwoFaNewPassword:\n case SettingsScreens.TwoFaChangePasswordNew:\n case SettingsScreens.TwoFaChangePasswordConfirm:\n return <h3>{lang('EnterPassword')}</h3>;\n case SettingsScreens.TwoFaNewPasswordConfirm:\n return <h3>{lang('PleaseReEnterPassword')}</h3>;\n case SettingsScreens.TwoFaNewPasswordHint:\n case SettingsScreens.TwoFaChangePasswordHint:\n return <h3>{lang('PasswordHint')}</h3>;\n case SettingsScreens.TwoFaNewPasswordEmail:\n case SettingsScreens.TwoFaRecoveryEmail:\n return <h3>{lang('RecoveryEmailTitle')}</h3>;\n case SettingsScreens.TwoFaNewPasswordEmailCode:\n case SettingsScreens.TwoFaRecoveryEmailCode:\n return <h3>Recovery Email Code</h3>;\n case SettingsScreens.TwoFaCongratulations:\n return <h3>{lang('TwoStepVerificationPasswordSet')}</h3>;\n case SettingsScreens.TwoFaChangePasswordCurrent:\n case SettingsScreens.TwoFaTurnOff:\n case SettingsScreens.TwoFaRecoveryEmailCurrentPassword:\n return <h3>{lang('PleaseEnterCurrentPassword')}</h3>;\n\n case SettingsScreens.Folders:\n return <h3>{lang('Filters')}</h3>;\n case SettingsScreens.FoldersCreateFolder:\n return <h3>{lang('FilterNew')}</h3>;\n case SettingsScreens.FoldersEditFolder:\n return (\n <div className=\"settings-main-header\">\n <h3>{lang('FilterEdit')}</h3>\n\n {editedFolderId && (\n <DropdownMenu\n className=\"settings-more-menu\"\n trigger={SettingsMenuButton}\n positionX=\"right\"\n >\n <MenuItem icon=\"delete\" destructive onClick={openDeleteFolderConfirmation}>Delete Folder</MenuItem>\n </DropdownMenu>\n )}\n </div>\n );\n case SettingsScreens.FoldersIncludedChats:\n case SettingsScreens.FoldersExcludedChats:\n return (\n <div className=\"settings-main-header\">\n {currentScreen === SettingsScreens.FoldersIncludedChats ? (\n <h3>{lang('FilterInclude')}</h3>\n ) : (\n <h3>{lang('FilterExclude')}</h3>\n )}\n\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n className=\"color-primary\"\n onClick={onSaveFilter}\n ariaLabel={lang('AutoDeleteConfirm')}\n >\n <i className=\"icon-check\" />\n </Button>\n </div>\n );\n\n default:\n return (\n <div className=\"settings-main-header\">\n <h3>{lang('SETTINGS')}</h3>\n\n <DropdownMenu\n className=\"settings-more-menu\"\n trigger={SettingsMenuButton}\n positionX=\"right\"\n >\n <MenuItem icon=\"logout\" onClick={openSignOutConfirmation}>{lang('LogOutTitle')}</MenuItem>\n </DropdownMenu>\n </div>\n );\n }\n }\n\n return (\n <div className=\"left-header\">\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={onReset}\n ariaLabel={lang('AccDescrGoBack')}\n >\n <i className=\"icon-arrow-left\" />\n </Button>\n {renderHeaderContent()}\n <ConfirmDialog\n isOpen={isSignOutDialogOpen}\n onClose={closeSignOutConfirmation}\n text=\"Are you sure you want to log out?\"\n confirmLabel=\"Log Out\"\n confirmHandler={handleSignOutMessage}\n confirmIsDestructive\n />\n <ConfirmDialog\n isOpen={isDeleteFolderDialogOpen}\n onClose={closeDeleteFolderConfirmation}\n text=\"Are you sure you want to delete this folder?\"\n confirmLabel=\"Delete\"\n confirmHandler={handleDeleteFolderMessage}\n confirmIsDestructive\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n undefined,\n (setGlobal, actions): DispatchProps => pick(actions, ['signOut', 'deleteChatFolder']),\n)(SettingsHeader));\n","import React, { FC, memo } from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { SettingsScreens } from '../../../types';\nimport { ApiUser } from '../../../api/types';\n\nimport { selectUser } from '../../../modules/selectors';\nimport { getUserFullName } from '../../../modules/helpers';\nimport { formatPhoneNumberWithCode } from '../../../util/phoneNumber';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport Avatar from '../../common/Avatar';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n currentUser?: ApiUser;\n};\n\nconst SettingsMain: FC<OwnProps & StateProps> = ({\n onScreenSelect,\n currentUser,\n}) => {\n const lang = useLang();\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-main-menu\">\n {currentUser && (\n <div className=\"settings-current-user\">\n <Avatar user={currentUser} size=\"jumbo\" />\n <p className=\"name\">{getUserFullName(currentUser)}</p>\n <p className=\"phone\">{formatPhoneNumberWithCode(currentUser.phoneNumber)}</p>\n </div>\n )}\n <ListItem\n icon=\"edit\"\n onClick={() => onScreenSelect(SettingsScreens.EditProfile)}\n >\n {lang('EditProfile')}\n </ListItem>\n <ListItem\n icon=\"folder\"\n onClick={() => onScreenSelect(SettingsScreens.Folders)}\n >\n {lang('Filters')}\n </ListItem>\n <ListItem\n icon=\"settings\"\n onClick={() => onScreenSelect(SettingsScreens.General)}\n >\n {lang('GeneralSettings')}\n </ListItem>\n <ListItem\n icon=\"unmute\"\n onClick={() => onScreenSelect(SettingsScreens.Notifications)}\n >\n {lang('Notifications')}\n </ListItem>\n <ListItem\n icon=\"lock\"\n onClick={() => onScreenSelect(SettingsScreens.Privacy)}\n >\n {lang('PrivacySettings')}\n </ListItem>\n <ListItem\n icon=\"language\"\n onClick={() => onScreenSelect(SettingsScreens.Language)}\n >\n {lang('Language')}\n </ListItem>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { currentUserId } = global;\n\n return {\n currentUser: currentUserId ? selectUser(global, currentUserId) : undefined,\n };\n },\n)(SettingsMain));\n","import React, { FC } from '../../lib/teact/teact';\n\nimport buildClassName from '../../util/buildClassName';\n\nimport Button, { OwnProps as ButtonProps } from './Button';\n\nimport './FloatingActionButton.scss';\n\ntype OwnProps = {\n isShown: boolean;\n className?: string;\n color?: ButtonProps['color'];\n ariaLabel?: ButtonProps['ariaLabel'];\n disabled?: boolean;\n onClick: () => void;\n children: any;\n};\n\nconst FloatingActionButton: FC<OwnProps> = ({\n isShown,\n className,\n color = 'primary',\n ariaLabel,\n disabled,\n onClick,\n children,\n}) => {\n const buttonClassName = buildClassName(\n 'FloatingActionButton',\n isShown && 'revealed',\n className,\n );\n\n return (\n <Button\n className={buttonClassName}\n color={color}\n round\n disabled={disabled}\n onClick={isShown && !disabled ? onClick : undefined}\n ariaLabel={ariaLabel}\n tabIndex={-1}\n >\n {children}\n </Button>\n );\n};\n\nexport default FloatingActionButton;\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, useState, useCallback, memo, useEffect, useMemo,\n} from '../../lib/teact/teact';\n\nimport { debounce } from '../../util/schedulers';\nimport useLang from '../../hooks/useLang';\n\nimport InputText from '../ui/InputText';\n\ntype OwnProps = {\n currentUsername?: string;\n asLink?: boolean;\n isLoading?: boolean;\n isUsernameAvailable?: boolean;\n checkUsername: AnyToVoidFunction;\n onChange: (value: string | false) => void;\n};\n\nconst MIN_USERNAME_LENGTH = 5;\nconst MAX_USERNAME_LENGTH = 32;\nconst LINK_PREFIX = 'https://t.me/';\nconst LINK_PREFIX_REGEX = /https:\\/\\/t\\.me\\/?/i;\nconst USERNAME_REGEX = /^([a-zA-Z0-9_]+)$/;\n\nconst runDebouncedForCheckUsername = debounce((cb) => cb(), 250, false);\n\nfunction isUsernameValid(username: string) {\n return username.length >= MIN_USERNAME_LENGTH\n && username.length <= MAX_USERNAME_LENGTH\n && USERNAME_REGEX.test(username);\n}\n\nconst SettingsEditProfile: FC<OwnProps> = ({\n currentUsername,\n asLink,\n isLoading,\n isUsernameAvailable,\n checkUsername,\n onChange,\n}) => {\n const [username, setUsername] = useState(currentUsername || '');\n\n const lang = useLang();\n const langPrefix = asLink ? 'SetUrl' : 'Username';\n const label = asLink ? lang('SetUrlPlaceholder') : lang('Username');\n\n const [usernameSuccess, usernameError] = useMemo(() => {\n if (!username.length) {\n return [];\n }\n\n if (username.length < MIN_USERNAME_LENGTH) {\n return [undefined, `${label} is too short`];\n }\n if (username.length > MAX_USERNAME_LENGTH) {\n return [undefined, `${label} is too long`];\n }\n if (!USERNAME_REGEX.test(username)) {\n return [undefined, `${label} contains invalid characters`];\n }\n\n if (isUsernameAvailable === undefined) {\n return [];\n }\n\n // Variable `isUsernameAvailable` is initialized with `undefined`, so a strict false check is required\n return [\n isUsernameAvailable ? lang(`${langPrefix}Available`, 'Username') : undefined,\n isUsernameAvailable === false ? lang(`${langPrefix}InUse`) : undefined,\n ];\n }, [username, isUsernameAvailable, lang, langPrefix, label]);\n\n useEffect(() => {\n setUsername(currentUsername || '');\n }, [asLink, currentUsername]);\n\n const handleUsernameChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const newUsername = e.target.value.trim().replace(LINK_PREFIX_REGEX, '');\n setUsername(newUsername);\n e.target.value = `${asLink ? LINK_PREFIX : ''}${newUsername}`;\n\n const isValid = isUsernameValid(newUsername);\n\n if (isValid) {\n runDebouncedForCheckUsername(() => {\n checkUsername({ username: newUsername });\n });\n }\n\n if (onChange) {\n onChange(isValid ? newUsername : false);\n }\n }, [asLink, checkUsername, onChange]);\n\n return (\n <InputText\n value={`${asLink ? LINK_PREFIX : ''}${username}`}\n onChange={handleUsernameChange}\n label={label}\n error={usernameError}\n success={usernameSuccess}\n readOnly={isLoading}\n />\n );\n};\n\nexport default memo(SettingsEditProfile);\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, useState, useCallback, memo, useEffect, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiMediaFormat } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\nimport { ProfileEditProgress } from '../../../types';\n\nimport { throttle } from '../../../util/schedulers';\nimport { pick } from '../../../util/iteratees';\nimport { selectUser } from '../../../modules/selectors';\nimport { getChatAvatarHash } from '../../../modules/helpers';\nimport useMedia from '../../../hooks/useMedia';\nimport useLang from '../../../hooks/useLang';\n\nimport AvatarEditable from '../../ui/AvatarEditable';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport InputText from '../../ui/InputText';\nimport renderText from '../../common/helpers/renderText';\nimport UsernameInput from '../../common/UsernameInput';\n\ntype StateProps = {\n currentAvatarHash?: string;\n currentFirstName?: string;\n currentLastName?: string;\n currentBio?: string;\n currentUsername?: string;\n progress?: ProfileEditProgress;\n isUsernameAvailable?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'loadCurrentUser' | 'updateProfile' | 'checkUsername'\n)>;\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst MAX_BIO_LENGTH = 70;\n\nconst ERROR_FIRST_NAME_MISSING = 'Please provide your first name';\nconst ERROR_BIO_TOO_LONG = 'Bio can\\' be longer than 70 characters';\n\nconst SettingsEditProfile: FC<StateProps & DispatchProps> = ({\n currentAvatarHash,\n currentFirstName,\n currentLastName,\n currentBio,\n currentUsername,\n progress,\n isUsernameAvailable,\n loadCurrentUser,\n updateProfile,\n checkUsername,\n}) => {\n const [isUsernameTouched, setIsUsernameTouched] = useState(false);\n const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);\n const [error, setError] = useState<string | undefined>();\n\n const [photo, setPhoto] = useState<File | undefined>();\n const [firstName, setFirstName] = useState(currentFirstName || '');\n const [lastName, setLastName] = useState(currentLastName || '');\n const [bio, setBio] = useState(currentBio || '');\n const [username, setUsername] = useState<string | false>(currentUsername || '');\n\n const currentAvatarBlobUrl = useMedia(currentAvatarHash, false, ApiMediaFormat.BlobUrl);\n\n const isLoading = progress === ProfileEditProgress.InProgress;\n const isUsernameError = username === false;\n\n const isSaveButtonShown = useMemo(() => {\n if (isUsernameError) {\n return false;\n }\n\n return Boolean(photo) || isProfileFieldsTouched || isUsernameAvailable === true;\n }, [photo, isProfileFieldsTouched, isUsernameError, isUsernameAvailable]);\n\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadCurrentUser();\n });\n }, [loadCurrentUser]);\n\n useEffect(() => {\n setPhoto(undefined);\n }, [currentAvatarBlobUrl]);\n\n useEffect(() => {\n setFirstName(currentFirstName || '');\n setLastName(currentLastName || '');\n setBio(currentBio || '');\n }, [currentFirstName, currentLastName, currentBio]);\n\n useEffect(() => {\n setUsername(currentUsername || '');\n }, [currentUsername]);\n\n useEffect(() => {\n if (progress === ProfileEditProgress.Complete) {\n setIsProfileFieldsTouched(false);\n setIsUsernameTouched(false);\n setError(undefined);\n }\n }, [progress]);\n\n const handlePhotoChange = useCallback((newPhoto: File) => {\n setPhoto(newPhoto);\n }, []);\n\n const handleFirstNameChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setFirstName(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleLastNameChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setLastName(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleBioChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setBio(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleUsernameChange = useCallback((value: string | false) => {\n setUsername(value);\n setIsUsernameTouched(true);\n }, []);\n\n const handleProfileSave = useCallback(() => {\n const trimmedFirstName = firstName.trim();\n const trimmedLastName = lastName.trim();\n const trimmedBio = bio.trim();\n\n if (!trimmedFirstName.length) {\n setError(ERROR_FIRST_NAME_MISSING);\n return;\n }\n\n if (trimmedBio.length > MAX_BIO_LENGTH) {\n setError(ERROR_BIO_TOO_LONG);\n return;\n }\n\n updateProfile({\n photo,\n ...(isProfileFieldsTouched && {\n firstName: trimmedFirstName,\n lastName: trimmedLastName,\n bio: trimmedBio,\n }),\n ...(isUsernameTouched && {\n username,\n }),\n });\n }, [\n photo,\n firstName, lastName, bio, isProfileFieldsTouched,\n username, isUsernameTouched,\n updateProfile,\n ]);\n\n const lang = useLang();\n\n return (\n <div className=\"settings-fab-wrapper\">\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-edit-profile\">\n <AvatarEditable\n currentAvatarBlobUrl={currentAvatarBlobUrl}\n onChange={handlePhotoChange}\n title=\"Edit your profile photo\"\n disabled={isLoading}\n />\n <InputText\n value={firstName}\n onChange={handleFirstNameChange}\n label={lang('FirstName')}\n disabled={isLoading}\n error={error === ERROR_FIRST_NAME_MISSING ? error : undefined}\n />\n <InputText\n value={lastName}\n onChange={handleLastNameChange}\n label={lang('LastName')}\n disabled={isLoading}\n />\n <InputText\n value={bio}\n onChange={handleBioChange}\n label={lang('UserBio')}\n disabled={isLoading}\n error={error === ERROR_BIO_TOO_LONG ? error : undefined}\n />\n\n <p className=\"settings-item-description\">\n {renderText(lang('BioAbout'), ['br', 'simple_markdown'])}\n </p>\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('Username')}</h4>\n\n <UsernameInput\n currentUsername={username || ''}\n isLoading={isLoading}\n isUsernameAvailable={isUsernameAvailable}\n checkUsername={checkUsername}\n onChange={handleUsernameChange}\n />\n\n <p className=\"settings-item-description\">\n {renderText(lang('UsernameHelp'), ['br', 'simple_markdown'])}\n </p>\n {username && (\n <p className=\"settings-item-description\">\n This link opens a chat with you:<br />\n <span className=\"username-link\">https://t.me/{username}</span>\n </p>\n )}\n </div>\n </div>\n\n <FloatingActionButton\n isShown={isSaveButtonShown}\n onClick={handleProfileSave}\n disabled={isLoading}\n ariaLabel=\"Save changes\"\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n </div>\n );\n};\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const { currentUserId } = global;\n const { progress, isUsernameAvailable } = global.profileEdit || {};\n const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined;\n\n if (!currentUser) {\n return {\n progress,\n isUsernameAvailable,\n };\n }\n\n const {\n firstName: currentFirstName,\n lastName: currentLastName,\n username: currentUsername,\n fullInfo,\n } = currentUser;\n const { bio: currentBio } = fullInfo || {};\n const currentAvatarHash = getChatAvatarHash(currentUser);\n\n return {\n currentAvatarHash,\n currentFirstName,\n currentLastName,\n currentBio,\n currentUsername,\n progress,\n isUsernameAvailable,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadCurrentUser',\n 'updateProfile',\n 'checkUsername',\n ]),\n)(SettingsEditProfile));\n","import React, {\n FC, memo, useMemo, useCallback, useState, useEffect,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../../global/types';\nimport { ApiChatFolder, ApiChat, ApiUser } from '../../../../api/types';\n\nimport { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config';\nimport { pick } from '../../../../util/iteratees';\nimport { throttle } from '../../../../util/schedulers';\nimport getAnimationData from '../../../common/helpers/animatedAssets';\nimport { getFolderDescriptionText } from '../../../../modules/helpers';\nimport useLang from '../../../../hooks/useLang';\n\nimport ListItem from '../../../ui/ListItem';\nimport Button from '../../../ui/Button';\nimport Loading from '../../../ui/Loading';\nimport AnimatedSticker from '../../../common/AnimatedSticker';\n\ntype OwnProps = {\n onCreateFolder: () => void;\n onEditFolder: (folder: ApiChatFolder) => void;\n};\n\ntype StateProps = {\n chatsById: Record<number, ApiChat>;\n usersById: Record<number, ApiUser>;\n orderedFolderIds?: number[];\n foldersById: Record<number, ApiChatFolder>;\n recommendedChatFolders?: ApiChatFolder[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadRecommendedChatFolders' | 'addChatFolder' | 'showError'>;\n\nconst runThrottledForLoadRecommended = throttle((cb) => cb(), 60000, true);\n\nconst MAX_ALLOWED_FOLDERS = 10;\n\nconst SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({\n onCreateFolder,\n onEditFolder,\n chatsById,\n usersById,\n orderedFolderIds,\n foldersById,\n recommendedChatFolders,\n loadRecommendedChatFolders,\n addChatFolder,\n showError,\n}) => {\n const [animationData, setAnimationData] = useState<Record<string, any>>();\n const [isAnimationLoaded, setIsAnimationLoaded] = useState(false);\n const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []);\n\n useEffect(() => {\n if (!animationData) {\n getAnimationData('FoldersAll').then(setAnimationData);\n }\n }, [animationData]);\n\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottledForLoadRecommended(() => {\n loadRecommendedChatFolders();\n });\n }, [loadRecommendedChatFolders]);\n\n const handleCreateFolder = useCallback(() => {\n if (Object.keys(foldersById).length >= MAX_ALLOWED_FOLDERS) {\n showError({\n error: {\n message: 'DIALOG_FILTERS_TOO_MUCH',\n },\n });\n\n return;\n }\n\n onCreateFolder();\n }, [foldersById, showError, onCreateFolder]);\n\n const lang = useLang();\n\n const userFolders = useMemo(() => {\n if (!orderedFolderIds) {\n return undefined;\n }\n\n const chatIds = Object.keys(chatsById).map(Number);\n\n return orderedFolderIds.map((id) => {\n const folder = foldersById[id];\n\n return {\n id: folder.id,\n title: folder.title,\n subtitle: getFolderDescriptionText(chatsById, usersById, folder, chatIds, lang),\n };\n });\n }, [orderedFolderIds, chatsById, foldersById, usersById, lang]);\n\n const handleCreateFolderFromRecommended = useCallback((folder: ApiChatFolder) => {\n if (Object.keys(foldersById).length >= MAX_ALLOWED_FOLDERS) {\n showError({\n error: {\n message: 'DIALOG_FILTERS_TOO_MUCH',\n },\n });\n\n return;\n }\n\n addChatFolder({ folder });\n }, [foldersById, addChatFolder, showError]);\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-content-header\">\n <div className=\"settings-content-icon\">\n {animationData && (\n <AnimatedSticker\n id=\"settingsFoldersMain\"\n size={STICKER_SIZE_FOLDER_SETTINGS}\n animationData={animationData}\n play={isAnimationLoaded}\n noLoop\n onLoad={handleAnimationLoad}\n />\n )}\n </div>\n\n <p className=\"settings-item-description mb-3\">\n {lang('CreateNewFilterInfo')}\n </p>\n\n <Button\n // TODO: Refactor button component to handle icon placemenet with props\n className=\"with-icon mb-2\"\n color=\"primary\"\n size=\"smaller\"\n pill\n fluid\n onClick={handleCreateFolder}\n >\n <i className=\"icon-add\" />\n {lang('CreateNewFilter')}\n </Button>\n </div>\n\n <div className=\"settings-item pt-3\">\n <h4 className=\"settings-item-header mb-3\">{lang('Filters')}</h4>\n\n {userFolders && userFolders.length ? userFolders.map((folder) => (\n <ListItem\n className=\"mb-2\"\n narrow\n onClick={() => onEditFolder(foldersById[folder.id])}\n >\n <div className=\"multiline-item\">\n <span className=\"title\">{folder.title}</span>\n <span className=\"subtitle\">{folder.subtitle}</span>\n </div>\n </ListItem>\n )) : userFolders && !userFolders.length ? (\n <p className=\"settings-item-description my-4\">\n You have no folders yet.\n </p>\n ) : <Loading />}\n </div>\n\n {(recommendedChatFolders && !!recommendedChatFolders.length) && (\n <div className=\"settings-item pt-3\">\n <h4 className=\"settings-item-header mb-3\">{lang('FilterRecommended')}</h4>\n\n {recommendedChatFolders.map((folder) => (\n <ListItem\n className=\"mb-2\"\n narrow\n onClick={() => handleCreateFolderFromRecommended(folder)}\n >\n <div className=\"settings-folders-recommended-item\">\n <div className=\"multiline-item\">\n <span className=\"title\">{folder.title}</span>\n <span className=\"subtitle\">{folder.description}</span>\n </div>\n\n <Button\n className=\"px-3\"\n color=\"primary\"\n size=\"tiny\"\n pill\n fluid\n >\n {lang('Add')}\n </Button>\n </div>\n </ListItem>\n ))}\n </div>\n )}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n chats: { byId: chatsById },\n users: { byId: usersById },\n } = global;\n\n const {\n orderedIds: orderedFolderIds,\n byId: foldersById,\n recommended: recommendedChatFolders,\n } = global.chatFolders;\n\n return {\n chatsById,\n usersById,\n orderedFolderIds,\n foldersById,\n recommendedChatFolders,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadRecommendedChatFolders', 'addChatFolder', 'showError']),\n)(SettingsFoldersMain));\n","import React, { FC } from '../../lib/teact/teact';\n\nimport Button from './Button';\n\nimport './ShowMoreButton.scss';\n\ntype OwnProps = {\n count: number;\n itemName: string;\n itemPluralName?: string;\n isLoading?: boolean;\n onClick: () => void;\n};\n\nconst ShowMoreButton: FC<OwnProps> = ({\n count,\n itemName,\n itemPluralName,\n isLoading,\n onClick,\n}) => {\n return (\n <Button\n className=\"ShowMoreButton\"\n color=\"translucent\"\n size=\"smaller\"\n isText\n isLoading={isLoading}\n onClick={onClick}\n >\n <i className=\"icon-down\" />\n Show {count} more {count > 1 ? itemPluralName || `${itemName}s` : itemName}\n </Button>\n );\n};\n\nexport default ShowMoreButton;\n","import React, {\n FC, memo, useCallback, useState, useEffect, useMemo,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../../global/types';\n\nimport { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config';\nimport { pick, findIntersectionWithSet } from '../../../../util/iteratees';\nimport { isChatPrivate } from '../../../../modules/helpers';\nimport getAnimationData from '../../../common/helpers/animatedAssets';\nimport {\n FoldersState,\n FolderEditDispatch,\n INCLUDED_CHAT_TYPES,\n EXCLUDED_CHAT_TYPES,\n selectChatFilters,\n} from '../../../../hooks/reducers/useFoldersReducer';\nimport useLang from '../../../../hooks/useLang';\n\nimport ListItem from '../../../ui/ListItem';\nimport AnimatedSticker from '../../../common/AnimatedSticker';\nimport InputText from '../../../ui/InputText';\nimport PrivateChatInfo from '../../../common/PrivateChatInfo';\nimport GroupChatInfo from '../../../common/GroupChatInfo';\nimport FloatingActionButton from '../../../ui/FloatingActionButton';\nimport Spinner from '../../../ui/Spinner';\nimport ShowMoreButton from '../../../ui/ShowMoreButton';\n\ntype OwnProps = {\n state: FoldersState;\n dispatch: FolderEditDispatch;\n onAddIncludedChats: () => void;\n onAddExcludedChats: () => void;\n onReset: () => void;\n};\n\ntype StateProps = {\n loadedActiveChatIds?: number[];\n loadedArchivedChatIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'editChatFolder' | 'addChatFolder' | 'loadMoreChats'>;\n\nconst SUBMIT_TIMEOUT = 500;\n\nconst INITIAL_CHATS_LIMIT = 5;\n\nconst ERROR_NO_TITLE = 'Please provide a title for this folder.';\nconst ERROR_NO_CHATS = 'Please select at least one chat for this folder.';\n\nconst SettingsFoldersEdit: FC<OwnProps & StateProps & DispatchProps> = ({\n state,\n dispatch,\n onAddIncludedChats,\n onAddExcludedChats,\n onReset,\n loadedActiveChatIds,\n loadedArchivedChatIds,\n editChatFolder,\n addChatFolder,\n loadMoreChats,\n}) => {\n const [animationData, setAnimationData] = useState<Record<string, any>>();\n const [isAnimationLoaded, setIsAnimationLoaded] = useState(false);\n const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []);\n\n const [isIncludedChatsListExpanded, setIsIncludedChatsListExpanded] = useState(false);\n const [isExcludedChatsListExpanded, setIsExcludedChatsListExpanded] = useState(false);\n\n const {\n selectedChatIds: includedChatIds,\n selectedChatTypes: includedChatTypes,\n } = selectChatFilters(state, 'included');\n const {\n selectedChatIds: excludedChatIds,\n selectedChatTypes: excludedChatTypes,\n } = selectChatFilters(state, 'excluded');\n\n useEffect(() => {\n if (!animationData) {\n getAnimationData('FoldersNew').then(setAnimationData);\n }\n }, [animationData]);\n\n useEffect(() => {\n setIsIncludedChatsListExpanded(false);\n setIsExcludedChatsListExpanded(false);\n }, [state.folderId]);\n\n const [visibleIncludedChatIds, visibleExcludedChatIds] = useMemo(() => {\n const allLoadedChatsSet = new Set([\n ...loadedActiveChatIds || [],\n ...loadedArchivedChatIds || [],\n ]);\n\n const loadedIncludedChatIds = findIntersectionWithSet(includedChatIds, allLoadedChatsSet);\n const loadedExcludedChatIds = findIntersectionWithSet(excludedChatIds, allLoadedChatsSet);\n\n return [\n isIncludedChatsListExpanded\n ? loadedIncludedChatIds\n : loadedIncludedChatIds.slice(0, INITIAL_CHATS_LIMIT - includedChatTypes.length),\n isExcludedChatsListExpanded\n ? loadedExcludedChatIds\n : loadedExcludedChatIds.slice(0, INITIAL_CHATS_LIMIT - excludedChatTypes.length),\n ];\n }, [\n excludedChatIds, includedChatIds, includedChatTypes, excludedChatTypes,\n isExcludedChatsListExpanded, isIncludedChatsListExpanded,\n loadedActiveChatIds, loadedArchivedChatIds,\n ]);\n\n useEffect(() => {\n if (\n visibleIncludedChatIds.length < includedChatIds.length\n || visibleExcludedChatIds.length < excludedChatIds.length\n ) {\n loadMoreChats({ listType: 'active' });\n }\n }, [\n loadMoreChats,\n excludedChatIds.length,\n includedChatIds.length,\n visibleExcludedChatIds.length,\n visibleIncludedChatIds.length,\n ]);\n\n const lang = useLang();\n\n function handleChange(event: React.ChangeEvent<HTMLInputElement>) {\n const { currentTarget } = event;\n dispatch({ type: 'setTitle', payload: currentTarget.value.trim() });\n }\n\n function handleSubmit() {\n const { title } = state.folder;\n\n if (!title) {\n dispatch({ type: 'setError', payload: ERROR_NO_TITLE });\n return;\n }\n\n if (!includedChatIds.length && !Object.keys(includedChatTypes).length) {\n dispatch({ type: 'setError', payload: ERROR_NO_CHATS });\n return;\n }\n\n dispatch({ type: 'setIsLoading', payload: true });\n if (state.mode === 'edit') {\n editChatFolder({ id: state.folderId, folderUpdate: state.folder });\n } else {\n addChatFolder({ folder: state.folder });\n }\n\n setTimeout(() => {\n onReset();\n }, SUBMIT_TIMEOUT);\n }\n\n function renderChatType(key: string, mode: 'included' | 'excluded') {\n const chatType = mode === 'included'\n ? INCLUDED_CHAT_TYPES.find(({ key: typeKey }) => typeKey === key)\n : EXCLUDED_CHAT_TYPES.find(({ key: typeKey }) => typeKey === key);\n\n if (!chatType) {\n return undefined;\n }\n\n return (\n <ListItem\n key={chatType.key}\n className=\"settings-folders-list-item mb-1\"\n icon={chatType.icon}\n narrow\n inactive\n >\n {lang(chatType.title)}\n </ListItem>\n );\n }\n\n function renderChats(mode: 'included' | 'excluded') {\n const selectedChatTypes = mode === 'included' ? includedChatTypes : excludedChatTypes;\n const visibleChatIds = mode === 'included' ? visibleIncludedChatIds : visibleExcludedChatIds;\n\n const isExpanded = mode === 'included' ? isIncludedChatsListExpanded : isExcludedChatsListExpanded;\n const allChatIds = mode === 'included' ? includedChatIds : excludedChatIds;\n const leftChatsCount = allChatIds.length - selectedChatTypes.length - visibleChatIds.length;\n const clickHandler = mode === 'included'\n ? () => setIsIncludedChatsListExpanded(true)\n : () => setIsExcludedChatsListExpanded(true);\n\n return (\n <>\n {selectedChatTypes.map((key) => renderChatType(key, mode))}\n {visibleChatIds.map((id) => (\n <ListItem\n className=\"settings-folders-list-item mb-1\"\n narrow\n inactive\n >\n {isChatPrivate(id) ? (\n <PrivateChatInfo avatarSize=\"small\" userId={id} />\n ) : (\n <GroupChatInfo avatarSize=\"small\" chatId={id} />\n )}\n </ListItem>\n ))}\n {(!isExpanded && leftChatsCount > 0) && (\n <ShowMoreButton\n count={leftChatsCount}\n itemName=\"chat\"\n onClick={clickHandler}\n />\n )}\n </>\n );\n }\n\n return (\n <div className=\"settings-fab-wrapper\">\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-content-header\">\n <div className=\"settings-content-icon\">\n {animationData && (\n <AnimatedSticker\n id=\"settingsFoldersEdit\"\n size={STICKER_SIZE_FOLDER_SETTINGS}\n animationData={animationData}\n play={isAnimationLoaded && String(state.folderId)}\n noLoop\n onLoad={handleAnimationLoad}\n />\n )}\n </div>\n\n {state.mode === 'create' && (\n <p className=\"settings-item-description mb-3\">\n {lang('FilterIncludeInfo')}\n </p>\n )}\n\n <InputText\n className=\"mb-0\"\n label={lang('FilterNameHint')}\n value={state.folder.title}\n onChange={handleChange}\n error={state.error && state.error === ERROR_NO_TITLE ? ERROR_NO_TITLE : undefined}\n />\n </div>\n\n <div className=\"settings-item no-border pt-3\">\n {state.error && state.error === ERROR_NO_CHATS && (\n <p className=\"settings-item-description color-danger mb-2\">\n {state.error}\n </p>\n )}\n\n <h4 className=\"settings-item-header mb-3\">{lang('FilterInclude')}</h4>\n\n <ListItem\n className=\"settings-folders-list-item color-primary mb-0\"\n icon=\"add\"\n onClick={onAddIncludedChats}\n >\n {lang('FilterAddChats')}\n </ListItem>\n\n {renderChats('included')}\n </div>\n\n <div className=\"settings-item no-border pt-3\">\n <h4 className=\"settings-item-header mb-3\">{lang('FilterExclude')}</h4>\n\n <ListItem\n className=\"settings-folders-list-item color-primary mb-0\"\n icon=\"add\"\n onClick={onAddExcludedChats}\n >\n {lang('FilterAddChats')}\n </ListItem>\n\n {renderChats('excluded')}\n </div>\n </div>\n\n <FloatingActionButton\n isShown={!!state.isTouched}\n disabled={state.isLoading}\n onClick={handleSubmit}\n ariaLabel={state.mode === 'edit' ? 'Save changes' : 'Create folder'}\n >\n {state.isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { listIds } = global.chats;\n\n return {\n loadedActiveChatIds: listIds.active,\n loadedArchivedChatIds: listIds.archived,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['editChatFolder', 'addChatFolder', 'loadMoreChats']),\n)(SettingsFoldersEdit));\n","import React, {\n FC, useCallback, useRef, useEffect, memo,\n} from '../../../../lib/teact/teact';\n\nimport { isChatPrivate } from '../../../../modules/helpers';\nimport {\n INCLUDED_CHAT_TYPES,\n EXCLUDED_CHAT_TYPES,\n FolderChatType,\n} from '../../../../hooks/reducers/useFoldersReducer';\nimport useInfiniteScroll from '../../../../hooks/useInfiniteScroll';\nimport useLang from '../../../../hooks/useLang';\n\nimport Checkbox from '../../../ui/Checkbox';\nimport InputText from '../../../ui/InputText';\nimport ListItem from '../../../ui/ListItem';\nimport PrivateChatInfo from '../../../common/PrivateChatInfo';\nimport GroupChatInfo from '../../../common/GroupChatInfo';\nimport PickerSelectedItem from '../../../common/PickerSelectedItem';\nimport InfiniteScroll from '../../../ui/InfiniteScroll';\nimport Loading from '../../../ui/Loading';\n\nimport '../../../common/Picker.scss';\nimport './SettingsFoldersChatsPicker.scss';\n\ntype OwnProps = {\n mode: 'included' | 'excluded';\n chatIds: number[];\n selectedIds: number[];\n selectedChatTypes: string[];\n filterValue?: string;\n onSelectedIdsChange: (ids: number[]) => void;\n onSelectedChatTypesChange: (types: string[]) => void;\n onFilterChange: (value: string) => void;\n onLoadMore: () => void;\n};\n\n// Focus slows down animation, also it breaks transition layout in Chrome\nconst FOCUS_DELAY_MS = 500;\n\nconst MAX_CHATS = 100;\nconst MAX_FULL_ITEMS = 10;\nconst ALWAYS_FULL_ITEMS_COUNT = 5;\n\nconst SettingsFoldersChatsPicker: FC<OwnProps> = ({\n mode,\n chatIds,\n selectedIds,\n selectedChatTypes,\n filterValue,\n onSelectedIdsChange,\n onSelectedChatTypesChange,\n onFilterChange,\n onLoadMore,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n const chatTypes = mode === 'included' ? INCLUDED_CHAT_TYPES : EXCLUDED_CHAT_TYPES;\n const shouldMinimize = selectedIds.length + selectedChatTypes.length > MAX_FULL_ITEMS;\n const hasMaxChats = selectedIds.length >= MAX_CHATS;\n\n useEffect(() => {\n setTimeout(() => {\n requestAnimationFrame(() => {\n inputRef.current!.focus();\n });\n }, FOCUS_DELAY_MS);\n }, []);\n\n const handleItemClick = useCallback((id: number) => {\n const newSelectedIds = [...selectedIds];\n if (newSelectedIds.includes(id)) {\n newSelectedIds.splice(newSelectedIds.indexOf(id), 1);\n } else {\n newSelectedIds.push(id);\n }\n onSelectedIdsChange(newSelectedIds);\n }, [selectedIds, onSelectedIdsChange]);\n\n const handleChatTypeClick = useCallback((key: FolderChatType['key']) => {\n const newSelectedChatTypes = [...selectedChatTypes];\n if (newSelectedChatTypes.includes(key)) {\n newSelectedChatTypes.splice(newSelectedChatTypes.indexOf(key), 1);\n } else {\n newSelectedChatTypes.push(key);\n }\n onSelectedChatTypesChange(newSelectedChatTypes);\n }, [selectedChatTypes, onSelectedChatTypesChange]);\n\n const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { value } = e.currentTarget;\n onFilterChange(value);\n }, [onFilterChange]);\n\n const lang = useLang();\n\n function renderSelectedChatType(key: string) {\n const selectedType = chatTypes.find(({ key: typeKey }) => key === typeKey);\n if (!selectedType) {\n return undefined;\n }\n\n return (\n <PickerSelectedItem\n icon={selectedType.icon}\n title={lang(selectedType.title)}\n isMinimized={shouldMinimize}\n canClose\n onClick={handleChatTypeClick}\n clickArg={selectedType.key}\n />\n );\n }\n\n function renderChatType(type: FolderChatType) {\n return (\n <ListItem\n key={type.key}\n className=\"chat-item-clickable picker-list-item chat-type-item\"\n onClick={() => handleChatTypeClick(type.key)}\n ripple\n >\n <i className={`icon-${type.icon}`} />\n <h3 className=\"chat-type\">{lang(type.title)}</h3>\n <Checkbox\n label=\"\"\n checked={selectedChatTypes.includes(type.key)}\n round\n />\n </ListItem>\n );\n }\n\n function renderItem(id: number) {\n const isSelected = selectedIds.includes(id);\n\n return (\n <ListItem\n key={id}\n className=\"chat-item-clickable picker-list-item chat-item\"\n onClick={() => handleItemClick(id)}\n ripple\n disabled={!isSelected && hasMaxChats}\n >\n {isChatPrivate(id) ? (\n <PrivateChatInfo userId={id} />\n ) : (\n <GroupChatInfo chatId={id} withChatType />\n )}\n <Checkbox\n label=\"\"\n checked={isSelected}\n round\n />\n </ListItem>\n );\n }\n\n const [viewportIds, getMore] = useInfiniteScroll(onLoadMore, chatIds, Boolean(filterValue));\n\n return (\n <div className=\"Picker SettingsFoldersChatsPicker\">\n <div className=\"picker-header custom-scroll\">\n {selectedChatTypes.map(renderSelectedChatType)}\n {selectedIds.map((id, i) => (\n <PickerSelectedItem\n chatOrUserId={id}\n isMinimized={shouldMinimize && i < selectedIds.length - ALWAYS_FULL_ITEMS_COUNT}\n canClose\n onClick={handleItemClick}\n clickArg={id}\n />\n ))}\n {!hasMaxChats ? (\n <InputText\n ref={inputRef}\n value={filterValue}\n onChange={handleFilterChange}\n placeholder={lang('Search')}\n />\n ) : (\n <p className=\"max-items-reached\">{`Sorry, you can't add more than ${MAX_CHATS} chats.`}</p>\n )}\n </div>\n <InfiniteScroll\n className=\"picker-list custom-scroll\"\n itemSelector=\".chat-item\"\n items={viewportIds}\n onLoadMore={getMore}\n >\n {(!viewportIds || !viewportIds.length || viewportIds.includes(chatIds[0])) && (\n <>\n <h4 key=\"header1\" className=\"settings-item-header\">{lang('FilterChatTypes')}</h4>\n {chatTypes.map(renderChatType)}\n <div key=\"divider\" className=\"picker-list-divider\" />\n <h4 key=\"header2\" className=\"settings-item-header\">{lang('FilterChats')}</h4>\n </>\n )}\n\n {viewportIds && viewportIds.length ? (\n viewportIds.map(renderItem)\n ) : viewportIds && !viewportIds.length ? (\n <p className=\"no-results\" key=\"no-results\">Sorry, nothing found.</p>\n ) : (\n <Loading key=\"loading\" />\n )}\n </InfiniteScroll>\n </div>\n );\n};\n\nexport default memo(SettingsFoldersChatsPicker);\n","import React, {\n FC, memo, useMemo, useCallback,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../../global/types';\nimport { ApiChat } from '../../../../api/types';\n\nimport { pick } from '../../../../util/iteratees';\nimport searchWords from '../../../../util/searchWords';\nimport { prepareChatList, getChatTitle } from '../../../../modules/helpers';\nimport {\n FoldersState,\n FolderEditDispatch,\n selectChatFilters,\n} from '../../../../hooks/reducers/useFoldersReducer';\n\nimport SettingsFoldersChatsPicker from './SettingsFoldersChatsPicker';\n\nimport Loading from '../../../ui/Loading';\n\ntype OwnProps = {\n mode: 'included' | 'excluded';\n state: FoldersState;\n dispatch: FolderEditDispatch;\n};\n\ntype StateProps = {\n chatsById: Record<number, ApiChat>;\n listIds?: number[];\n orderedPinnedIds?: number[];\n archivedListIds?: number[];\n archivedPinnedIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadMoreChats'>;\n\nconst SettingsFoldersChatFilters: FC<OwnProps & StateProps & DispatchProps> = ({\n mode,\n state,\n dispatch,\n chatsById,\n listIds,\n orderedPinnedIds,\n archivedListIds,\n archivedPinnedIds,\n loadMoreChats,\n}) => {\n const { chatFilter } = state;\n const { selectedChatIds, selectedChatTypes } = selectChatFilters(state, mode, true);\n\n const chats = useMemo(() => {\n const activeChatArrays = listIds\n ? prepareChatList(chatsById, listIds, orderedPinnedIds, 'all')\n : undefined;\n const archivedChatArrays = archivedListIds\n ? prepareChatList(chatsById, archivedListIds, archivedPinnedIds, 'archived')\n : undefined;\n\n if (!activeChatArrays && !archivedChatArrays) {\n return undefined;\n }\n\n return [\n ...(activeChatArrays\n ? [...activeChatArrays.pinnedChats, ...activeChatArrays.otherChats]\n : []\n ),\n ...(archivedChatArrays ? archivedChatArrays.otherChats : []),\n ];\n }, [chatsById, listIds, orderedPinnedIds, archivedListIds, archivedPinnedIds]);\n\n const displayedIds = useMemo(() => {\n if (!chats) {\n return undefined;\n }\n\n return chats\n .filter((chat) => (\n !chatFilter\n || searchWords(getChatTitle(chat), chatFilter)\n || selectedChatIds.includes(chat.id)\n ))\n .map(({ id }) => id);\n }, [chats, chatFilter, selectedChatIds]);\n\n const handleFilterChange = useCallback((newFilter: string) => {\n dispatch({\n type: 'setChatFilter',\n payload: newFilter,\n });\n }, [dispatch]);\n\n const handleSelectedIdsChange = useCallback((ids: number[]) => {\n if (mode === 'included') {\n dispatch({\n type: 'setIncludeFilters',\n payload: { ...state.includeFilters, includedChatIds: ids },\n });\n } else {\n dispatch({\n type: 'setExcludeFilters',\n payload: { ...state.excludeFilters, excludedChatIds: ids },\n });\n }\n }, [mode, state, dispatch]);\n\n const handleSelectedChatTypesChange = useCallback((keys: string[]) => {\n const newFilters: Record<string, boolean> = {};\n keys.forEach((key) => {\n newFilters[key] = true;\n });\n\n if (mode === 'included') {\n dispatch({\n type: 'setIncludeFilters',\n payload: {\n includedChatIds: selectedChatIds,\n ...newFilters,\n },\n });\n } else {\n dispatch({\n type: 'setExcludeFilters',\n payload: {\n excludedChatIds: selectedChatIds,\n ...newFilters,\n },\n });\n }\n }, [mode, selectedChatIds, dispatch]);\n\n if (!displayedIds) {\n return <Loading />;\n }\n\n return (\n <SettingsFoldersChatsPicker\n mode={mode}\n chatIds={displayedIds}\n selectedIds={selectedChatIds}\n selectedChatTypes={selectedChatTypes}\n filterValue={chatFilter}\n onSelectedIdsChange={handleSelectedIdsChange}\n onSelectedChatTypesChange={handleSelectedChatTypesChange}\n onFilterChange={handleFilterChange}\n onLoadMore={loadMoreChats}\n />\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n chats: {\n byId: chatsById,\n listIds,\n orderedPinnedIds,\n },\n } = global;\n\n return {\n chatsById,\n listIds: listIds.active,\n orderedPinnedIds: orderedPinnedIds.active,\n archivedPinnedIds: orderedPinnedIds.archived,\n archivedListIds: listIds.archived,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadMoreChats']),\n)(SettingsFoldersChatFilters));\n","import React, { FC, memo, useCallback } from '../../../../lib/teact/teact';\n\nimport { ApiChatFolder } from '../../../../api/types';\nimport { SettingsScreens } from '../../../../types';\n\nimport { FoldersState, FolderEditDispatch } from '../../../../hooks/reducers/useFoldersReducer';\n\nimport SettingsFoldersMain from './SettingsFoldersMain';\nimport SettingsFoldersEdit from './SettingsFoldersEdit';\nimport SettingsFoldersChatFilters from './SettingsFoldersChatFilters';\n\nimport './SettingsFolders.scss';\n\nconst TRANSITION_DURATION = 200;\n\nexport type OwnProps = {\n currentScreen: SettingsScreens;\n state: FoldersState;\n dispatch: FolderEditDispatch;\n onScreenSelect: (screen: SettingsScreens) => void;\n onReset: () => void;\n};\n\nconst SettingsFolders: FC<OwnProps> = ({\n currentScreen,\n state,\n dispatch,\n onScreenSelect,\n onReset,\n}) => {\n const handleReset = useCallback(() => {\n if (\n currentScreen === SettingsScreens.FoldersCreateFolder\n || currentScreen === SettingsScreens.FoldersEditFolder\n ) {\n setTimeout(() => {\n dispatch({ type: 'reset' });\n }, TRANSITION_DURATION);\n }\n\n if (\n currentScreen === SettingsScreens.FoldersIncludedChats\n || currentScreen === SettingsScreens.FoldersExcludedChats\n ) {\n if (state.mode === 'create') {\n onScreenSelect(SettingsScreens.FoldersCreateFolder);\n } else {\n onScreenSelect(SettingsScreens.FoldersEditFolder);\n }\n return;\n }\n\n onReset();\n }, [\n state.mode, dispatch,\n currentScreen, onReset, onScreenSelect,\n ]);\n\n const handleCreateFolder = useCallback(() => {\n dispatch({ type: 'reset' });\n onScreenSelect(SettingsScreens.FoldersCreateFolder);\n }, [onScreenSelect, dispatch]);\n\n const handleEditFolder = useCallback((folder: ApiChatFolder) => {\n dispatch({ type: 'editFolder', payload: folder });\n onScreenSelect(SettingsScreens.FoldersEditFolder);\n }, [dispatch, onScreenSelect]);\n\n const handleAddIncludedChats = useCallback(() => {\n dispatch({ type: 'editIncludeFilters' });\n onScreenSelect(SettingsScreens.FoldersIncludedChats);\n }, [dispatch, onScreenSelect]);\n\n const handleAddExcludedChats = useCallback(() => {\n dispatch({ type: 'editExcludeFilters' });\n onScreenSelect(SettingsScreens.FoldersExcludedChats);\n }, [dispatch, onScreenSelect]);\n\n switch (currentScreen) {\n case SettingsScreens.Folders:\n return (\n <SettingsFoldersMain\n onCreateFolder={handleCreateFolder}\n onEditFolder={handleEditFolder}\n />\n );\n case SettingsScreens.FoldersCreateFolder:\n case SettingsScreens.FoldersEditFolder:\n return (\n <SettingsFoldersEdit\n state={state}\n dispatch={dispatch}\n onAddIncludedChats={handleAddIncludedChats}\n onAddExcludedChats={handleAddExcludedChats}\n onReset={handleReset}\n />\n );\n case SettingsScreens.FoldersIncludedChats:\n return (\n <SettingsFoldersChatFilters\n mode=\"included\"\n state={state}\n dispatch={dispatch}\n />\n );\n case SettingsScreens.FoldersExcludedChats:\n return (\n <SettingsFoldersChatFilters\n mode=\"excluded\"\n state={state}\n dispatch={dispatch}\n />\n );\n\n default:\n return undefined;\n }\n};\n\nexport default memo(SettingsFolders);\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, useCallback, useMemo, memo,\n} from '../../lib/teact/teact';\n\nimport buildClassName from '../../util/buildClassName';\n\nimport './RangeSlider.scss';\n\ntype OwnProps = {\n options?: string[];\n range?: { min: number; max: number; step?: number };\n label?: string;\n value: number;\n disabled?: boolean;\n onChange: (value: number) => void;\n};\n\nconst RangeSlider: FC<OwnProps> = ({\n options,\n range,\n label,\n value,\n disabled,\n onChange,\n}) => {\n const handleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {\n onChange(Number(event.currentTarget.value));\n }, [onChange]);\n\n const className = buildClassName(\n 'RangeSlider',\n disabled && 'disabled',\n );\n\n const trackWidth = useMemo(() => {\n if (options) {\n return (value / (options.length - 1)) * 100;\n } else if (range) {\n const possibleValuesLength = (range.max - range.min) / (range.step || 1);\n return ((value - range.min) / possibleValuesLength) * 100;\n }\n return 0;\n }, [value, options, range]);\n\n const [min, max, step] = useMemo(() => {\n if (options) {\n return [0, options.length - 1, 1];\n } else if (range) {\n return [range.min, range.max, range.step || 1];\n }\n\n return [0, 0, 0];\n }, [range, options]);\n\n return (\n <div className={className}>\n {label && (\n <div className=\"slider-top-row\">\n <span className=\"label\">{label}</span>\n {range && (\n <span className=\"value\">{value}</span>\n )}\n </div>\n )}\n <div className=\"slider-main\">\n <div\n className=\"slider-fill-track\"\n // @ts-ignore\n style={`width: ${trackWidth}%`}\n />\n <input\n min={min}\n max={max}\n value={value}\n step={step}\n type=\"range\"\n onChange={handleChange}\n />\n {options && (\n <div className=\"slider-options\">\n {options.map((option, index) => (\n <div\n className={buildClassName('slider-option no-selection', index === value && 'active')}\n onClick={() => onChange(index)}\n >\n {option}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default memo(RangeSlider);\n","import React, { FC, memo, useRef } from '../../../lib/teact/teact';\n\nimport { ApiMediaFormat, ApiStickerSet } from '../../../api/types';\n\nimport { STICKER_SIZE_PICKER_HEADER } from '../../../config';\nimport { ObserveFn, useIsIntersecting } from '../../../hooks/useIntersectionObserver';\nimport useMedia from '../../../hooks/useMedia';\nimport useTransitionForMedia from '../../../hooks/useTransitionForMedia';\nimport { getFirstLetters } from '../../../util/textFormat';\n\nimport AnimatedSticker from '../../common/AnimatedSticker';\n\ntype OwnProps = {\n size?: number;\n stickerSet: ApiStickerSet;\n observeIntersection: ObserveFn;\n};\n\nconst StickerSetCoverAnimated: FC<OwnProps> = ({\n size = STICKER_SIZE_PICKER_HEADER,\n stickerSet,\n observeIntersection,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n\n const isIntersecting = useIsIntersecting(ref, observeIntersection);\n\n const mediaHash = `stickerSet${stickerSet.id}`;\n const lottieData = useMedia(mediaHash, !isIntersecting, ApiMediaFormat.Lottie);\n const { shouldRenderFullMedia, transitionClassNames } = useTransitionForMedia(lottieData, 'slow');\n\n return (\n <div ref={ref} className=\"sticker-set-cover\">\n {!shouldRenderFullMedia && getFirstLetters(stickerSet.title, 2)}\n {shouldRenderFullMedia && lottieData && (\n <AnimatedSticker\n id={mediaHash}\n size={size}\n animationData={lottieData}\n className={transitionClassNames}\n />\n )}\n </div>\n );\n};\n\nexport default memo(StickerSetCoverAnimated);\n","import React, { FC, memo, useRef } from '../../../lib/teact/teact';\n\nimport { ApiStickerSet } from '../../../api/types';\n\nimport { ObserveFn, useIsIntersecting } from '../../../hooks/useIntersectionObserver';\nimport useMedia from '../../../hooks/useMedia';\nimport useTransitionForMedia from '../../../hooks/useTransitionForMedia';\nimport { getFirstLetters } from '../../../util/textFormat';\n\ntype OwnProps = {\n stickerSet: ApiStickerSet;\n observeIntersection: ObserveFn;\n};\n\nconst StickerSetCover: FC<OwnProps> = ({ stickerSet, observeIntersection }) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n\n const isIntersecting = useIsIntersecting(ref, observeIntersection);\n\n const mediaData = useMedia(stickerSet.hasThumbnail && `stickerSet${stickerSet.id}`, !isIntersecting);\n const { shouldRenderFullMedia, transitionClassNames } = useTransitionForMedia(mediaData, 'slow');\n\n return (\n <div ref={ref} className=\"sticker-set-cover\">\n {!shouldRenderFullMedia && getFirstLetters(stickerSet.title, 2)}\n {shouldRenderFullMedia && (\n <img src={mediaData} className={transitionClassNames} alt=\"\" />\n )}\n </div>\n );\n};\n\nexport default memo(StickerSetCover);\n","import { MouseEvent as ReactMouseEvent } from 'react';\nimport React, {\n FC, memo, useEffect, useRef,\n} from '../../lib/teact/teact';\n\nimport { ApiMediaFormat, ApiSticker } from '../../api/types';\n\nimport { useIsIntersecting, ObserveFn } from '../../hooks/useIntersectionObserver';\nimport useMedia from '../../hooks/useMedia';\nimport useTransitionForMedia from '../../hooks/useTransitionForMedia';\nimport useFlag from '../../hooks/useFlag';\nimport buildClassName from '../../util/buildClassName';\n\nimport AnimatedSticker from './AnimatedSticker';\nimport Button from '../ui/Button';\n\nimport './StickerButton.scss';\n\ntype OwnProps = {\n sticker: ApiSticker;\n size: number;\n observeIntersection: ObserveFn;\n noAnimate?: boolean;\n title?: string;\n className?: string;\n onClick?: (arg: any) => void;\n clickArg?: any;\n onUnfaveClick?: (sticker: ApiSticker) => void;\n};\n\nconst StickerButton: FC<OwnProps> = ({\n sticker, size, observeIntersection, noAnimate, title, className, onClick, clickArg, onUnfaveClick,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n\n const { isAnimated } = sticker;\n const localMediaHash = `sticker${sticker.id}`;\n const stickerSelector = `sticker-button-${sticker.id}`;\n\n const isIntersecting = useIsIntersecting(ref, observeIntersection);\n\n const thumbDataUri = sticker.thumbnail ? sticker.thumbnail.dataUri : undefined;\n const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !isIntersecting, ApiMediaFormat.BlobUrl);\n\n const shouldPlay = isIntersecting && !noAnimate;\n const lottieData = useMedia(localMediaHash, !shouldPlay, ApiMediaFormat.Lottie);\n const [isAnimationLoaded, markLoaded, unmarkLoaded] = useFlag(Boolean(lottieData));\n const canAnimatedPlay = isAnimationLoaded && shouldPlay;\n\n const {\n shouldRenderThumb,\n shouldRenderFullMedia: shouldRenderPreview,\n transitionClassNames: previewTransitionClassNames,\n } = useTransitionForMedia(previewBlobUrl || canAnimatedPlay, 'slow');\n\n // To avoid flickering\n useEffect(() => {\n if (!shouldPlay) {\n unmarkLoaded();\n }\n }, [unmarkLoaded, shouldPlay]);\n\n function handleClick() {\n if (onClick) {\n onClick(clickArg);\n }\n }\n\n function handleUnfaveClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\n e.stopPropagation();\n e.preventDefault();\n\n onUnfaveClick!(sticker);\n }\n\n const fullClassName = buildClassName(\n 'StickerButton',\n isAnimated && 'animated',\n stickerSelector,\n className,\n );\n\n const style = shouldRenderThumb && thumbDataUri ? `background-image: url('${thumbDataUri}');` : '';\n\n return (\n <div\n ref={ref}\n className={fullClassName}\n title={title || (sticker && sticker.emoji)}\n // @ts-ignore\n style={style}\n data-sticker-id={sticker.id}\n onClick={handleClick}\n >\n {shouldRenderPreview && !canAnimatedPlay && (\n // eslint-disable-next-line jsx-a11y/alt-text\n <img src={previewBlobUrl} className={previewTransitionClassNames} />\n )}\n {shouldPlay && lottieData && (\n <AnimatedSticker\n id={localMediaHash}\n animationData={lottieData}\n play\n size={size}\n isLowPriority\n onLoad={markLoaded}\n />\n )}\n {onUnfaveClick && (\n <Button\n className=\"sticker-unfave-button\"\n color=\"dark\"\n round\n onClick={handleUnfaveClick}\n >\n <i className=\"icon-close\" />\n </Button>\n )}\n </div>\n );\n};\n\nexport default memo(StickerButton);\n","import React, {\n FC, memo,\n} from '../../../lib/teact/teact';\nimport { ApiSticker, ApiStickerSet } from '../../../api/types';\n\nimport { STICKER_SIZE_GENERAL_SETTINGS } from '../../../config';\nimport { ObserveFn } from '../../../hooks/useIntersectionObserver';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport Button from '../../ui/Button';\nimport StickerSetCoverAnimated from '../../middle/composer/StickerSetCoverAnimated';\nimport StickerSetCover from '../../middle/composer/StickerSetCover';\nimport StickerButton from '../../common/StickerButton';\n\nimport './SettingsStickerSet.scss';\n\ntype OwnProps = {\n stickerSet?: ApiStickerSet;\n observeIntersection: ObserveFn;\n onClick: (value: ApiSticker) => void;\n};\n\nconst SettingsStickerSet: FC<OwnProps> = ({\n stickerSet,\n observeIntersection,\n onClick,\n}) => {\n const lang = useLang();\n\n if (!stickerSet || !stickerSet.stickers) {\n return undefined;\n }\n\n const firstSticker = stickerSet.stickers && stickerSet.stickers[0];\n\n if (stickerSet.hasThumbnail || !firstSticker) {\n return (\n <ListItem\n narrow\n className=\"SettingsStickerSet\"\n inactive={!firstSticker}\n onClick={() => firstSticker && onClick(firstSticker)}\n >\n <Button\n ariaLabel={stickerSet.title}\n color=\"translucent\"\n >\n {stickerSet.isAnimated ? (\n <StickerSetCoverAnimated\n size={STICKER_SIZE_GENERAL_SETTINGS}\n stickerSet={stickerSet}\n observeIntersection={observeIntersection}\n />\n ) : (\n <StickerSetCover\n stickerSet={stickerSet}\n observeIntersection={observeIntersection}\n />\n )}\n </Button>\n <div className=\"multiline-menu-item\">\n <div className=\"title\">{stickerSet.title}</div>\n <div className=\"subtitle\">{lang('StickerPack.StickerCount', stickerSet.count, 'i')}</div>\n </div>\n </ListItem>\n );\n } else {\n return (\n <ListItem\n narrow\n className=\"SettingsStickerSet\"\n onClick={() => onClick(firstSticker)}\n >\n <StickerButton\n sticker={firstSticker}\n size={STICKER_SIZE_GENERAL_SETTINGS}\n title={stickerSet.title}\n observeIntersection={observeIntersection}\n />\n <div className=\"multiline-menu-item\">\n <div className=\"title\">{stickerSet.title}</div>\n <div className=\"subtitle\">{lang('StickerPack.StickerCount', stickerSet.count, 'i')}</div>\n </div>\n </ListItem>\n );\n }\n};\n\nexport default memo(SettingsStickerSet);\n","import React, {\n FC, useCallback, memo, useEffect, useRef, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { SettingsScreens, ISettings } from '../../../types';\nimport { ApiSticker, ApiStickerSet } from '../../../api/types';\n\nimport { IS_MAC_OS, IS_TOUCH_ENV } from '../../../util/environment';\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\nimport useFlag from '../../../hooks/useFlag';\nimport { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';\n\nimport ListItem from '../../ui/ListItem';\nimport RangeSlider from '../../ui/RangeSlider';\nimport Checkbox from '../../ui/Checkbox';\nimport RadioGroup from '../../ui/RadioGroup';\nimport SettingsStickerSet from './SettingsStickerSet';\nimport StickerSetModal from '../../common/StickerSetModal.async';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = ISettings['byKey'] & {\n stickerSetIds?: string[];\n stickerSetsById?: Record<string, ApiStickerSet>;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setSettingOption' | 'loadStickerSets' | 'loadAddedStickers'>;\n\nconst KEYBOARD_SEND_OPTIONS = !IS_TOUCH_ENV ? [\n { value: 'enter', label: 'Send by Enter', subLabel: 'New line by Shift + Enter' },\n { value: 'ctrl-enter', label: `Send by ${IS_MAC_OS ? 'Cmd' : 'Ctrl'} + Enter`, subLabel: 'New line by Enter' },\n] : undefined;\n\nconst ANIMATION_LEVEL_OPTIONS = [\n 'Solid and Steady',\n 'Nice and Fast',\n 'Lots of Stuff',\n];\n\nconst SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({\n onScreenSelect,\n stickerSetIds,\n stickerSetsById,\n messageTextSize,\n animationLevel,\n messageSendKeyCombo,\n shouldAutoDownloadMediaFromContacts,\n shouldAutoDownloadMediaInPrivateChats,\n shouldAutoDownloadMediaInGroups,\n shouldAutoDownloadMediaInChannels,\n shouldAutoPlayGifs,\n shouldAutoPlayVideos,\n shouldSuggestStickers,\n shouldLoopStickers,\n setSettingOption,\n loadStickerSets,\n loadAddedStickers,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const stickerSettingsRef = useRef<HTMLDivElement>(null);\n const { observe: observeIntersectionForCovers } = useIntersectionObserver({ rootRef: stickerSettingsRef });\n const [isModalOpen, openModal, closeModal] = useFlag();\n const [sticker, setSticker] = useState<ApiSticker>();\n\n useEffect(() => {\n loadStickerSets();\n }, [loadStickerSets]);\n\n useEffect(() => {\n if (stickerSetIds && stickerSetIds.length) {\n loadAddedStickers();\n }\n }, [stickerSetIds, loadAddedStickers]);\n\n const handleAnimationLevelChange = useCallback((newLevel: number) => {\n ANIMATION_LEVEL_OPTIONS.forEach((_, i) => {\n document.body.classList.toggle(`animation-level-${i}`, newLevel === i);\n });\n\n setSettingOption({ animationLevel: newLevel });\n }, [setSettingOption]);\n\n const handleMessageTextSizeChange = useCallback((newSize: number) => {\n document.documentElement.style.setProperty('--message-text-size', `${newSize}px`);\n\n setSettingOption({ messageTextSize: newSize });\n }, [setSettingOption]);\n\n const handleStickerSetClick = useCallback((value: ApiSticker) => {\n setSticker(value);\n openModal();\n }, [openModal]);\n\n const lang = useLang();\n\n\n const stickerSets = stickerSetIds && stickerSetIds.map((id: string) => {\n return stickerSetsById && stickerSetsById[id] && stickerSetsById[id].installedDate ? stickerSetsById[id] : false;\n }).filter(Boolean);\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-item pt-3\">\n <h4 className=\"settings-item-header\">{lang('SETTINGS')}</h4>\n\n <RangeSlider\n label={lang('TextSize')}\n // TODO Remove memo-killer\n range={{ min: 12, max: 20 }}\n value={messageTextSize}\n onChange={handleMessageTextSizeChange}\n />\n\n <ListItem\n icon=\"photo\"\n onClick={() => onScreenSelect(SettingsScreens.GeneralChatBackground)}\n >\n {lang('ChatBackground')}\n </ListItem>\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">\n Animation Level\n </h4>\n <p className=\"settings-item-description\">Choose the desired animations amount.</p>\n\n <RangeSlider\n options={ANIMATION_LEVEL_OPTIONS}\n value={animationLevel}\n onChange={handleAnimationLevelChange}\n />\n </div>\n\n {KEYBOARD_SEND_OPTIONS && (\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('Keyboard')}</h4>\n\n <RadioGroup\n name=\"keyboard-send-settings\"\n options={KEYBOARD_SEND_OPTIONS}\n onChange={(value) => setSettingOption({ messageSendKeyCombo: value })}\n selected={messageSendKeyCombo}\n />\n </div>\n )}\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('AutoDownloadMedia')}</h4>\n\n <Checkbox\n label={lang('Contacts')}\n checked={shouldAutoDownloadMediaFromContacts}\n onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaFromContacts: isChecked })}\n />\n <Checkbox\n label={lang('AutodownloadPrivateChats')}\n checked={shouldAutoDownloadMediaInPrivateChats}\n onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInPrivateChats: isChecked })}\n />\n <Checkbox\n label={lang('AutodownloadGroupChats')}\n checked={shouldAutoDownloadMediaInGroups}\n onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInGroups: isChecked })}\n />\n <Checkbox\n label={lang('FilterChannels')}\n checked={shouldAutoDownloadMediaInChannels}\n onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInChannels: isChecked })}\n />\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('AutoplayMedia')}</h4>\n\n <Checkbox\n label={lang('GifsTab2')}\n checked={shouldAutoPlayGifs}\n onCheck={(isChecked) => setSettingOption({ shouldAutoPlayGifs: isChecked })}\n />\n <Checkbox\n label={lang('VideosTitle')}\n checked={shouldAutoPlayVideos}\n onCheck={(isChecked) => setSettingOption({ shouldAutoPlayVideos: isChecked })}\n />\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('AccDescrStickers')}</h4>\n\n <Checkbox\n label={lang('SuggestStickers')}\n checked={shouldSuggestStickers}\n onCheck={(isChecked) => setSettingOption({ shouldSuggestStickers: isChecked })}\n />\n <Checkbox\n label={lang('LoopAnimatedStickers')}\n checked={shouldLoopStickers}\n onCheck={(isChecked) => setSettingOption({ shouldLoopStickers: isChecked })}\n />\n\n <div className=\"mt-4\" ref={stickerSettingsRef}>\n {stickerSets && stickerSets.map((stickerSet: ApiStickerSet) => (\n <SettingsStickerSet\n key={stickerSet.id}\n stickerSet={stickerSet}\n observeIntersection={observeIntersectionForCovers}\n onClick={handleStickerSetClick}\n />\n ))}\n </div>\n {sticker && (\n <StickerSetModal\n isOpen={isModalOpen}\n fromSticker={sticker}\n onClose={closeModal}\n />\n )}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n return {\n ...pick(global.settings.byKey,\n [\n 'messageTextSize',\n 'animationLevel',\n 'messageSendKeyCombo',\n 'shouldAutoDownloadMediaFromContacts',\n 'shouldAutoDownloadMediaInPrivateChats',\n 'shouldAutoDownloadMediaInGroups',\n 'shouldAutoDownloadMediaInChannels',\n 'shouldAutoPlayGifs',\n 'shouldAutoPlayVideos',\n 'shouldSuggestStickers',\n 'shouldLoopStickers',\n ]),\n stickerSetIds: global.stickers.added.setIds,\n stickerSetsById: global.stickers.setsById,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'setSettingOption', 'loadStickerSets', 'loadAddedStickers',\n ]),\n)(SettingsGeneral));\n","let fileSelector: HTMLInputElement;\n\nexport function openSystemFilesDialog(accept = '*', callback: (e: Event) => void, noMultiple = false) {\n if (!fileSelector) {\n fileSelector = document.createElement('input');\n fileSelector.setAttribute('type', 'file');\n }\n\n fileSelector.setAttribute('accept', accept);\n\n if (noMultiple) {\n fileSelector.removeAttribute('multiple');\n } else {\n fileSelector.setAttribute('multiple', 'multiple');\n }\n\n // eslint-disable-next-line no-null/no-null\n fileSelector.onchange = null;\n fileSelector.value = '';\n fileSelector.onchange = callback;\n\n fileSelector.click();\n}\n","/* eslint-disable eqeqeq */\n/* eslint-disable prefer-template */\n/* eslint-disable prefer-const */\n/* eslint-disable prefer-destructuring */\n/* eslint-disable one-var */\n/* eslint-disable one-var-declaration-per-line */\n\nimport { preloadImage } from './files';\n\n/**\n * HEX > RGB\n * input: 'xxxxxx' (ex. 'ed15fa') case-insensitive\n * output: [r, g, b] ([0-255, 0-255, 0-255])\n */\nexport function hex2rgb(param: string): [number, number, number] {\n return [\n parseInt(param.substring(0, 2), 16),\n parseInt(param.substring(2, 4), 16),\n parseInt(param.substring(4, 6), 16),\n ];\n}\n\n/**\n * RGB > HEX\n * input: [r, g, b] ([0-255, 0-255, 0-255])\n * output: 'xxxxxx' (ex. 'ff0000')\n */\nexport function rgb2hex(param: [number, number, number]) {\n const p0 = param[0].toString(16);\n const p1 = param[1].toString(16);\n const p2 = param[2].toString(16);\n return (p0.length == 1 ? '0' + p0 : p0) + (p1.length == 1 ? '0' + p1 : p1) + (p2.length == 1 ? '0' + p2 : p2);\n}\n\n/**\n * Converts an RGB color value to HSV. Conversion formula\n * adapted from http://en.wikipedia.org/wiki/HSV_color_space.\n * Assumes r, g, and b are contained in the set [0, 255] and\n * returns h, s, and v in the set [0, 1].\n *\n * @param Number r The red color value\n * @param Number g The green color value\n * @param Number b The blue color value\n * @return Array The HSV representation\n */\nexport function rgb2hsb([r, g, b]: [number, number, number]): [number, number, number] {\n r /= 255;\n g /= 255;\n b /= 255;\n\n let max = Math.max(r, g, b), min = Math.min(r, g, b);\n let h!: number, s: number, v: number = max;\n\n let d = max - min;\n s = max == 0 ? 0 : d / max;\n\n if (max == min) {\n h = 0; // achromatic\n } else {\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\n h /= 6;\n }\n\n return [h, s, v];\n}\n\n/**\n * Converts an HSV color value to RGB. Conversion formula\n * adapted from http://en.wikipedia.org/wiki/HSV_color_space.\n * Assumes h, s, and v are contained in the set [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 v The value\n * @return Array The RGB representation\n */\nexport function hsb2rgb([h, s, v]: [number, number, number]): [number, number, number] {\n let r!: number, g!: number, b!: number;\n\n let i = Math.floor(h * 6);\n let f = h * 6 - i;\n let p = v * (1 - s);\n let q = v * (1 - f * s);\n let t = v * (1 - (1 - f) * s);\n\n switch (i % 6) {\n case 0:\n r = v;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = v;\n b = p;\n break;\n case 2:\n r = p;\n g = v;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = v;\n break;\n case 4:\n r = t;\n g = p;\n b = v;\n break;\n case 5:\n r = v;\n g = p;\n b = q;\n break;\n }\n\n return [\n Math.round(r * 255),\n Math.round(g * 255),\n Math.round(b * 255),\n ];\n}\n\nexport async function getAverageColor(url: string): Promise<[number, number, number]> {\n // Only visit every 5 pixels\n const blockSize = 5;\n const defaultRGB: [number, number, number] = [0, 0, 0];\n let data;\n let width;\n let height;\n let i = -4;\n let length;\n let rgb: [number, number, number] = [0, 0, 0];\n let count = 0;\n\n const canvas = document.createElement('canvas');\n const context = canvas.getContext && canvas.getContext('2d');\n if (!context) {\n return defaultRGB;\n }\n\n const image = await preloadImage(url);\n height = image.naturalHeight || image.offsetHeight || image.height;\n width = image.naturalWidth || image.offsetWidth || image.width;\n canvas.height = height;\n canvas.width = width;\n\n context.drawImage(image, 0, 0);\n\n try {\n data = context.getImageData(0, 0, width, height);\n } catch (e) {\n return defaultRGB;\n }\n\n length = data.data.length;\n\n // eslint-disable-next-line no-cond-assign\n while ((i += blockSize * 4) < length) {\n ++count;\n rgb[0] += data.data[i];\n rgb[1] += data.data[i + 1];\n rgb[2] += data.data[i + 2];\n }\n\n rgb[0] = Math.floor(rgb[0] / count);\n rgb[1] = Math.floor(rgb[1] / count);\n rgb[2] = Math.floor(rgb[2] / count);\n\n return rgb;\n}\n\n// eslint-disable-next-line max-len\n// Function was adapted from https://github.com/telegramdesktop/tdesktop/blob/35ff621b5b52f7e3553fb0f990ea13ade7101b8e/Telegram/SourceFiles/data/data_wall_paper.cpp#L518\nexport function getPatternColor(rgbColor: [number, number, number]) {\n let [hue, saturation, value] = rgb2hsb(rgbColor);\n\n saturation = Math.min(1, saturation + 0.05 + 0.1 * (1 - saturation));\n value = value > 0.5\n ? Math.max(0, value * 0.65)\n : Math.max(0, Math.min(1, 1 - value * 0.65));\n\n return `hsla(${hue * 360}, ${saturation * 100}%, ${value * 100}%, .4)`;\n}\n","import React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { ApiWallpaper } from '../../../api/types';\nimport { UPLOADING_WALLPAPER_SLUG } from '../../../types';\n\nimport { CUSTOM_BG_CACHE_NAME } from '../../../config';\nimport * as cacheApi from '../../../util/cacheApi';\nimport { fetchBlob } from '../../../util/files';\nimport useTransitionForMedia from '../../../hooks/useTransitionForMedia';\nimport buildClassName from '../../../util/buildClassName';\nimport useMedia from '../../../hooks/useMedia';\nimport useMediaWithDownloadProgress from '../../../hooks/useMediaWithDownloadProgress';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport usePrevious from '../../../hooks/usePrevious';\nimport useBlur from '../../../hooks/useBlur';\n\nimport ProgressSpinner from '../../ui/ProgressSpinner';\n\nimport './WallpaperTile.scss';\n\ntype OwnProps = {\n wallpaper: ApiWallpaper;\n isSelected: boolean;\n onClick: (slug: string) => void;\n};\n\nconst ANIMATION_DURATION = 300;\n\nconst WallpaperTile: FC<OwnProps> = ({\n wallpaper,\n isSelected,\n onClick,\n}) => {\n const { slug, document } = wallpaper;\n\n const localMediaHash = `wallpaper${document.id!}`;\n const localBlobUrl = document.previewBlobUrl;\n const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);\n const thumbDataUri = useBlur(\n document.thumbnail && document.thumbnail.dataUri,\n Boolean(previewBlobUrl),\n ANIMATION_DURATION,\n );\n const {\n shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,\n } = useTransitionForMedia(previewBlobUrl || localBlobUrl, 'slow');\n const [isDownloadAllowed, setIsDownloadAllowed] = useState(false);\n const {\n mediaData: fullMedia, downloadProgress,\n } = useMediaWithDownloadProgress(localMediaHash, !isDownloadAllowed);\n const wasDownloadDisabled = usePrevious(isDownloadAllowed) === false;\n const { shouldRender: shouldRenderSpinner, transitionClassNames: spinnerClassNames } = useShowTransition(\n (isDownloadAllowed && !fullMedia) || slug === UPLOADING_WALLPAPER_SLUG,\n undefined,\n wasDownloadDisabled,\n 'slow',\n );\n\n const handleSelect = useCallback(() => {\n (async () => {\n const blob = await fetchBlob(fullMedia!);\n await cacheApi.save(CUSTOM_BG_CACHE_NAME, CUSTOM_BG_CACHE_NAME, blob);\n onClick(slug);\n })();\n }, [fullMedia, onClick, slug]);\n\n useEffect(() => {\n if (fullMedia) {\n handleSelect();\n }\n }, [fullMedia, handleSelect]);\n\n const handleClick = useCallback(() => {\n if (fullMedia) {\n handleSelect();\n } else {\n setIsDownloadAllowed((isAllowed) => !isAllowed);\n }\n }, [fullMedia, handleSelect]);\n\n const className = buildClassName(\n 'WallpaperTile',\n isSelected && 'selected',\n );\n\n return (\n <div className={className} onClick={handleClick}>\n <div className=\"media-inner\">\n {shouldRenderThumb && (\n <img\n src={thumbDataUri}\n className=\"thumbnail\"\n alt=\"\"\n />\n )}\n {shouldRenderFullMedia && (\n <img\n src={previewBlobUrl || localBlobUrl}\n className={`full-media ${transitionClassNames}`}\n alt=\"\"\n />\n )}\n {shouldRenderSpinner && (\n <div className={buildClassName('spinner-container', spinnerClassNames)}>\n <ProgressSpinner progress={downloadProgress} onClick={handleClick} />\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default memo(WallpaperTile);\n","import React, {\n FC, memo, useEffect, useCallback,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { SettingsScreens, UPLOADING_WALLPAPER_SLUG } from '../../../types';\nimport { ApiWallpaper } from '../../../api/types';\n\nimport { DEFAULT_PATTERN_COLOR } from '../../../config';\nimport { pick } from '../../../util/iteratees';\nimport { throttle } from '../../../util/schedulers';\nimport { openSystemFilesDialog } from '../../../util/systemFilesDialog';\nimport { getAverageColor, getPatternColor } from '../../../util/colors';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport Loading from '../../ui/Loading';\nimport WallpaperTile from './WallpaperTile';\n\nimport './SettingsGeneralBackground.scss';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n customBackground?: string;\n isBackgroundBlurred?: boolean;\n loadedWallpapers?: ApiWallpaper[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setSettingOption' | 'loadWallpapers' | 'uploadWallpaper'>;\n\nconst SUPPORTED_TYPES = 'image/jpeg';\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({\n onScreenSelect,\n customBackground,\n isBackgroundBlurred,\n loadedWallpapers,\n setSettingOption,\n loadWallpapers,\n uploadWallpaper,\n}) => {\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadWallpapers();\n });\n }, [loadWallpapers]);\n\n const handleFileSelect = useCallback((e: Event) => {\n const { files } = e.target as HTMLInputElement;\n\n if (files && files.length > 0) {\n uploadWallpaper(files[0]);\n }\n }, [uploadWallpaper]);\n\n const handleUploadWallpaper = useCallback(() => {\n openSystemFilesDialog(SUPPORTED_TYPES, handleFileSelect, true);\n }, [handleFileSelect]);\n\n const handleSetColor = useCallback(() => {\n onScreenSelect(SettingsScreens.GeneralChatBackgroundColor);\n }, [onScreenSelect]);\n\n const handleResetToDefault = useCallback(() => {\n setSettingOption({ customBackground: undefined, patternColor: DEFAULT_PATTERN_COLOR });\n }, [setSettingOption]);\n\n const handleWallPaperSelect = useCallback((slug: string) => {\n setSettingOption({ customBackground: slug });\n const currentWallpaper = loadedWallpapers && loadedWallpapers.find((wallpaper) => wallpaper.slug === slug);\n if (currentWallpaper && currentWallpaper.document.thumbnail) {\n getAverageColor(currentWallpaper.document.thumbnail.dataUri)\n .then((color) => {\n setSettingOption({ patternColor: getPatternColor(color) });\n });\n }\n }, [loadedWallpapers, setSettingOption]);\n\n const handleWallPaperBlurChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setSettingOption({ isBackgroundBlurred: e.target.checked });\n }, [setSettingOption]);\n\n const lang = useLang();\n\n const isUploading = loadedWallpapers && loadedWallpapers[0] && loadedWallpapers[0].slug === UPLOADING_WALLPAPER_SLUG;\n\n return (\n <div className=\"SettingsGeneralBackground settings-content custom-scroll\">\n <div className=\"settings-item pt-3\">\n <ListItem\n icon=\"camera-add\"\n className=\"mb-0\"\n disabled={isUploading}\n onClick={handleUploadWallpaper}\n >\n {lang('UploadImage')}\n </ListItem>\n\n <ListItem\n icon=\"colorize\"\n className=\"mb-0\"\n onClick={handleSetColor}\n >\n {lang('SetColor')}\n </ListItem>\n\n <ListItem icon=\"favorite\" onClick={handleResetToDefault}>\n {lang('ThemeResetToDefaults')}\n </ListItem>\n\n <Checkbox\n label={lang('BackgroundBlurred')}\n checked={Boolean(isBackgroundBlurred)}\n onChange={handleWallPaperBlurChange}\n />\n </div>\n\n {loadedWallpapers ? (\n <div className=\"settings-wallpapers\">\n {loadedWallpapers.map((wallpaper) => (\n <WallpaperTile\n wallpaper={wallpaper}\n isSelected={customBackground === wallpaper.slug}\n onClick={handleWallPaperSelect}\n />\n ))}\n </div>\n ) : (\n <Loading />\n )}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { isBackgroundBlurred, customBackground } = global.settings.byKey;\n const { loadedWallpapers } = global.settings;\n\n return {\n customBackground,\n isBackgroundBlurred,\n loadedWallpapers,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'setSettingOption', 'loadWallpapers', 'uploadWallpaper',\n ]),\n)(SettingsGeneralBackground));\n","import { ChangeEvent, MutableRefObject, RefObject } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect, useRef, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { SettingsScreens } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport {\n getPatternColor, hex2rgb, hsb2rgb, rgb2hex, rgb2hsb,\n} from '../../../util/colors';\nimport { captureEvents, RealTouchEvent } from '../../../util/captureEvents';\nimport useFlag from '../../../hooks/useFlag';\nimport buildClassName from '../../../util/buildClassName';\n\nimport InputText from '../../ui/InputText';\n\nimport './SettingsGeneralBackgroundColor.scss';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n customBackground?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setSettingOption'>;\n\ninterface CanvasRects {\n colorRect: {\n offsetLeft: number;\n top: number;\n width: number;\n height: number;\n };\n hueRect: {\n offsetLeft: number;\n width: number;\n };\n}\n\nconst DEFAULT_HSB = rgb2hsb(hex2rgb('e6ebee'));\nconst PREDEFINED_COLORS = [\n '#e6ebee', '#b2cee1', '#008dd0', '#c6e7cb', '#c4e1a6', '#60b16e',\n '#ccd0af', '#a6a997', '#7a7072', '#fdd7af', '#fdb76e', '#dd8851',\n];\n\nconst SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({\n customBackground,\n setSettingOption,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const colorPickerRef = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const huePickerRef = useRef<HTMLDivElement>(null);\n const isFirstRunRef = useRef(true);\n\n const [hsb, setHsb] = useState(getInitialHsb(customBackground));\n // Cache for drag handlers\n const hsbRef = useRef(hsb);\n useEffect(() => {\n hsbRef.current = hsb;\n }, [hsb]);\n\n const [isDragging, markIsDragging, unmarkIsDragging] = useFlag();\n const [rgbInput, setRgbInput] = useState('');\n const [hexInput, setHexInput] = useState('');\n\n const rectsRef = useRef<CanvasRects>();\n const colorCtxRef = useRef<CanvasRenderingContext2D>();\n\n // Setup: cache rects, subscribe for drag events\n useEffect(() => {\n // We use `offsetLeft` instead of `left` to support screen transition\n const colorRect = {\n offsetLeft: colorPickerRef.current!.offsetLeft,\n ...pick(colorPickerRef.current!.getBoundingClientRect(), ['top', 'width', 'height']),\n };\n const hueRect = {\n offsetLeft: huePickerRef.current!.offsetLeft,\n ...pick(huePickerRef.current!.getBoundingClientRect(), ['width']),\n };\n\n rectsRef.current = { colorRect, hueRect };\n\n function handleColorDrag(e: MouseEvent | RealTouchEvent) {\n const colorPosition = [\n Math.min(Math.max(0, e.pageX! - colorRect.offsetLeft), colorRect.width - 1),\n Math.min(Math.max(0, e.pageY! - colorRect.top + containerRef.current!.scrollTop), colorRect.height - 1),\n ];\n\n const { huePosition } = hsb2positions(hsbRef.current, rectsRef.current!);\n\n setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));\n markIsDragging();\n }\n\n captureEvents(colorPickerRef.current!, {\n onCapture: handleColorDrag,\n onDrag: handleColorDrag,\n onRelease: unmarkIsDragging,\n onClick: unmarkIsDragging,\n withCursor: true,\n });\n\n function handleHueDrag(e: MouseEvent | RealTouchEvent) {\n const { colorPosition } = hsb2positions(hsbRef.current, rectsRef.current!);\n const huePosition = Math.min(Math.max(0, e.pageX! - hueRect.offsetLeft), hueRect.width - 1);\n\n setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));\n markIsDragging();\n }\n\n captureEvents(huePickerRef.current!, {\n onCapture: handleHueDrag,\n onDrag: handleHueDrag,\n onRelease: unmarkIsDragging,\n onClick: unmarkIsDragging,\n withCursor: true,\n });\n }, [markIsDragging, unmarkIsDragging]);\n\n const { colorPosition = [0, 0], huePosition = 0 } = rectsRef.current ? hsb2positions(hsb, rectsRef.current) : {};\n const hex = rgb2hex(hsb2rgb(hsb));\n const hue = hsb[0];\n const hueHex = rgb2hex(hsb2rgb([hue, 1, 1]));\n\n // Save value and update inputs when HSL changes\n useEffect(() => {\n const rgb = hsb2rgb(hsb);\n const color = `#${rgb2hex(rgb)}`;\n\n setRgbInput(rgb.join(', '));\n setHexInput(color);\n\n if (!isFirstRunRef.current) {\n setSettingOption({\n customBackground: color,\n patternColor: getPatternColor(rgb),\n });\n }\n isFirstRunRef.current = false;\n }, [hsb, setSettingOption]);\n\n // Redraw color picker when hue changes\n useEffect(() => {\n drawColor(colorPickerRef.current!.firstChild as HTMLCanvasElement, hue, colorCtxRef, rectsRef);\n }, [hue]);\n\n // Initially draw hue picker\n useEffect(() => {\n drawHue(huePickerRef.current!.firstChild as HTMLCanvasElement);\n }, []);\n\n const handleRgbChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const rgbValue = e.currentTarget.value.replace(/[^\\d, ]/g, '').slice(0, 13);\n\n if (rgbValue.match(/^\\d{1,3},\\s?\\d{1,3},\\s?\\d{1,3}$/)) {\n const rgb = rgbValue.split(',').map((channel) => Number(channel.trim())) as [number, number, number];\n setHsb(rgb2hsb(rgb));\n }\n\n e.currentTarget.value = rgbValue;\n }, []);\n\n const handleHexChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n const hexValue = e.currentTarget.value.replace(/[^0-9a-fA-F]/g, '').slice(0, 6);\n\n if (hexValue.match(/^#?[0-9a-fA-F]{6}$/)) {\n setHsb(rgb2hsb(hex2rgb(hexValue.replace('#', ''))));\n }\n\n e.currentTarget.value = hexValue;\n }, []);\n\n const handlePredefinedColorClick = useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n setHsb(rgb2hsb(hex2rgb(e.currentTarget.dataset.color!.replace('#', ''))));\n }, []);\n\n const className = buildClassName(\n 'SettingsGeneralBackgroundColor settings-content custom-scroll',\n isDragging && 'is-dragging',\n );\n\n return (\n <div ref={containerRef} className={className}>\n <div className=\"settings-item pt-3\">\n <div ref={colorPickerRef} className=\"color-picker\">\n <canvas />\n <div\n className=\"handle\"\n // @ts-ignore\n style={`transform: translate(${colorPosition[0]}px, ${colorPosition[1]}px); background-color: #${hex};`}\n />\n </div>\n <div ref={huePickerRef} className=\"hue-picker\">\n <canvas />\n <div\n className=\"handle\"\n // @ts-ignore\n style={`transform: translateX(${huePosition}px); background-color: #${hueHex};`}\n />\n </div>\n <div className=\"tools\">\n <InputText value={hexInput} label=\"HEX\" onChange={handleHexChange} />\n <InputText value={rgbInput} label=\"RGB\" onChange={handleRgbChange} />\n </div>\n </div>\n <div className=\"predefined-colors\">\n {PREDEFINED_COLORS.map((color) => (\n <div\n className={color === `#${hex}` ? 'active' : undefined}\n data-color={color}\n // @ts-ignore\n style={`background-color: ${color};`}\n onClick={handlePredefinedColorClick}\n />\n ))}\n </div>\n </div>\n );\n};\n\nfunction getInitialHsb(customBackground?: string) {\n return customBackground && customBackground.startsWith('#')\n ? rgb2hsb(hex2rgb(customBackground.replace('#', '')))\n : DEFAULT_HSB;\n}\n\nfunction hsb2positions(hsb: [number, number, number], rects: CanvasRects) {\n return {\n colorPosition: [\n Math.round((hsb[1]) * (rects.colorRect.width - 1)),\n Math.round((1 - hsb[2]) * (rects.colorRect.height - 1)),\n ],\n huePosition: Math.round(hsb[0] * (rects.hueRect.width - 1)),\n };\n}\n\nfunction positions2hsb(\n { colorPosition, huePosition }: { colorPosition: number[]; huePosition: number },\n rects: CanvasRects,\n): [number, number, number] {\n return [\n huePosition / (rects.hueRect.width - 1),\n colorPosition[0] / (rects.colorRect.width - 1),\n 1 - colorPosition[1] / (rects.colorRect.height - 1),\n ];\n}\n\nfunction drawColor(\n canvas: HTMLCanvasElement,\n hue: number,\n colorCtxRef: MutableRefObject<CanvasRenderingContext2D | undefined>,\n rectsRef: RefObject<CanvasRects | undefined>,\n) {\n let w: number;\n let h: number;\n let ctx: CanvasRenderingContext2D;\n\n if (!colorCtxRef.current || !rectsRef.current) {\n // First run\n w = canvas.offsetWidth;\n h = canvas.offsetHeight;\n ctx = canvas.getContext('2d')!;\n\n canvas.width = w;\n canvas.height = h;\n\n colorCtxRef.current = ctx;\n } else {\n w = rectsRef.current.colorRect.width;\n h = rectsRef.current.colorRect.height;\n ctx = colorCtxRef.current;\n }\n\n const imgData = ctx!.createImageData(w, h);\n const pixels = imgData.data;\n const col = hsb2rgb([hue, 1, 1]);\n\n let index = 0;\n\n for (let y = 0; y < h; y++) {\n const perY = 1 - y / (h - 1);\n const st = [255 * perY, 255 * perY, 255 * perY];\n const ed = [col[0] * perY, col[1] * perY, col[2] * perY];\n for (let x = 0; x < w; x++) {\n const perX = x / (w - 1);\n pixels[index++] = st[0] + (ed[0] - st[0]) * perX;\n pixels[index++] = st[1] + (ed[1] - st[1]) * perX;\n pixels[index++] = st[2] + (ed[2] - st[2]) * perX;\n pixels[index++] = 255;\n }\n }\n\n ctx!.putImageData(imgData, 0, 0);\n}\n\nfunction drawHue(canvas: HTMLCanvasElement) {\n const w = canvas.offsetWidth;\n const h = 1;\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext('2d')!;\n\n const imgData = ctx.createImageData(w, h);\n const pixels = imgData.data;\n\n let index = 0;\n\n for (let x = 0; x < w; x++) {\n const hue = x / (w - 1);\n const rgb = hsb2rgb([hue, 1, 1]);\n /* eslint-disable prefer-destructuring */\n pixels[index++] = rgb[0];\n pixels[index++] = rgb[1];\n pixels[index++] = rgb[2];\n /* eslint-enable prefer-destructuring */\n pixels[index++] = 255;\n }\n\n ctx.putImageData(imgData, 0, 0);\n}\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n return {\n customBackground: global.settings.byKey.customBackground,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['setSettingOption']),\n)(SettingsGeneralBackground));\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\n\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\n\nimport Checkbox from '../../ui/Checkbox';\n\ntype StateProps = {\n hasPrivateChatsNotifications: boolean;\n hasPrivateChatsMessagePreview: boolean;\n hasGroupNotifications: boolean;\n hasGroupMessagePreview: boolean;\n hasBroadcastNotifications: boolean;\n hasBroadcastMessagePreview: boolean;\n hasContactJoinedNotifications: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'loadNotificationsSettings' | 'updateContactSignUpNotification' | 'updateNotificationSettings'\n)>;\n\nconst SettingsNotifications: FC<StateProps & DispatchProps> = ({\n hasPrivateChatsNotifications,\n hasPrivateChatsMessagePreview,\n hasGroupNotifications,\n hasGroupMessagePreview,\n hasBroadcastNotifications,\n hasBroadcastMessagePreview,\n hasContactJoinedNotifications,\n loadNotificationsSettings,\n updateContactSignUpNotification,\n updateNotificationSettings,\n}) => {\n useEffect(() => {\n loadNotificationsSettings();\n }, [loadNotificationsSettings]);\n\n const handleSettingsChange = useCallback((\n e: ChangeEvent<HTMLInputElement>,\n peerType: 'contact' | 'group' | 'broadcast',\n setting: 'silent' | 'showPreviews',\n ) => {\n const currentIsSilent = peerType === 'contact'\n ? !hasPrivateChatsNotifications\n : !(peerType === 'group' ? hasGroupNotifications : hasBroadcastNotifications);\n const currentIsShowPreviews = peerType === 'contact'\n ? hasPrivateChatsMessagePreview\n : (peerType === 'group' ? hasGroupMessagePreview : hasBroadcastMessagePreview);\n\n updateNotificationSettings({\n peerType,\n ...(setting === 'silent' && { isSilent: !e.target.checked, isShowPreviews: currentIsShowPreviews }),\n ...(setting === 'showPreviews' && { isShowPreviews: e.target.checked, isSilent: currentIsSilent }),\n });\n }, [\n hasBroadcastMessagePreview, hasBroadcastNotifications,\n hasGroupMessagePreview, hasGroupNotifications,\n hasPrivateChatsMessagePreview, hasPrivateChatsNotifications,\n updateNotificationSettings,\n ]);\n\n const handleContactNotificationChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n updateContactSignUpNotification({\n isSilent: !e.target.checked,\n });\n }, [updateContactSignUpNotification]);\n\n const lang = useLang();\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('AutodownloadPrivateChats')}</h4>\n\n <Checkbox\n label={lang('NotificationsForPrivateChats')}\n subLabel={lang(hasPrivateChatsNotifications ? 'NotificationsEnabled' : 'NotificationsDisabled')}\n checked={hasPrivateChatsNotifications}\n onChange={(e) => { handleSettingsChange(e, 'contact', 'silent'); }}\n />\n <Checkbox\n label={lang('MessagePreview')}\n subLabel={lang(hasPrivateChatsMessagePreview ? 'PreviewEnabled' : 'PreviewDisabled')}\n checked={hasPrivateChatsMessagePreview}\n onChange={(e) => { handleSettingsChange(e, 'contact', 'showPreviews'); }}\n />\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('FilterGroups')}</h4>\n\n <Checkbox\n label={lang('NotificationsForGroups')}\n subLabel={lang(hasGroupNotifications ? 'NotificationsEnabled' : 'NotificationsDisabled')}\n checked={hasGroupNotifications}\n onChange={(e) => { handleSettingsChange(e, 'group', 'silent'); }}\n />\n <Checkbox\n label={lang('MessagePreview')}\n subLabel={lang(hasGroupMessagePreview ? 'PreviewEnabled' : 'PreviewDisabled')}\n checked={hasGroupMessagePreview}\n onChange={(e) => { handleSettingsChange(e, 'group', 'showPreviews'); }}\n />\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('FilterChannels')}</h4>\n\n <Checkbox\n label={lang('NotificationsForChannels')}\n subLabel={lang(hasBroadcastNotifications ? 'NotificationsEnabled' : 'NotificationsDisabled')}\n checked={hasBroadcastNotifications}\n onChange={(e) => { handleSettingsChange(e, 'broadcast', 'silent'); }}\n />\n <Checkbox\n label={lang('MessagePreview')}\n subLabel={lang(hasBroadcastMessagePreview ? 'PreviewEnabled' : 'PreviewDisabled')}\n checked={hasBroadcastMessagePreview}\n onChange={(e) => { handleSettingsChange(e, 'broadcast', 'showPreviews'); }}\n />\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{lang('PhoneOther')}</h4>\n\n <Checkbox\n label={lang('ContactJoined')}\n checked={hasContactJoinedNotifications}\n onChange={handleContactNotificationChange}\n />\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal((global): StateProps => {\n return {\n hasPrivateChatsNotifications: Boolean(global.settings.byKey.hasPrivateChatsNotifications),\n hasPrivateChatsMessagePreview: Boolean(global.settings.byKey.hasPrivateChatsMessagePreview),\n hasGroupNotifications: Boolean(global.settings.byKey.hasGroupNotifications),\n hasGroupMessagePreview: Boolean(global.settings.byKey.hasGroupMessagePreview),\n hasBroadcastNotifications: Boolean(global.settings.byKey.hasBroadcastNotifications),\n hasBroadcastMessagePreview: Boolean(global.settings.byKey.hasBroadcastMessagePreview),\n hasContactJoinedNotifications: Boolean(global.settings.byKey.hasContactJoinedNotifications),\n };\n},\n(setGlobal, actions): DispatchProps => pick(actions, [\n 'loadNotificationsSettings',\n 'updateContactSignUpNotification',\n 'updateNotificationSettings',\n]))(SettingsNotifications));\n","import React, { FC, memo, useEffect } from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { PrivacyVisibility, SettingsScreens } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n hasPassword?: boolean;\n blockedCount: number;\n sessionsCount: number;\n visibilityPrivacyPhoneNumber?: PrivacyVisibility;\n visibilityPrivacyLastSeen?: PrivacyVisibility;\n visibilityPrivacyProfilePhoto?: PrivacyVisibility;\n visibilityPrivacyForwarding?: PrivacyVisibility;\n visibilityPrivacyGroupChats?: PrivacyVisibility;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadBlockedContacts' | 'loadAuthorizations' | 'loadPrivacySettings'>;\n\nconst SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({\n onScreenSelect,\n hasPassword,\n blockedCount,\n sessionsCount,\n visibilityPrivacyPhoneNumber,\n visibilityPrivacyLastSeen,\n visibilityPrivacyProfilePhoto,\n visibilityPrivacyForwarding,\n visibilityPrivacyGroupChats,\n loadPrivacySettings,\n loadBlockedContacts,\n loadAuthorizations,\n}) => {\n useEffect(() => {\n loadBlockedContacts();\n loadAuthorizations();\n loadPrivacySettings();\n }, [loadBlockedContacts, loadAuthorizations, loadPrivacySettings]);\n\n const lang = useLang();\n\n function getVisibilityValue(visibility?: PrivacyVisibility) {\n switch (visibility) {\n case 'everybody':\n return lang('P2PEverybody');\n\n case 'contacts':\n return lang('P2PContacts');\n\n case 'nobody':\n return lang('P2PNobody');\n }\n\n return undefined;\n }\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-item pt-3\">\n <ListItem\n icon=\"delete-user\"\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyBlockedUsers)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('BlockedUsers')}</span>\n {blockedCount > 0 && (\n <span className=\"subtitle\">\n {lang('Users', blockedCount)}\n </span>\n )}\n </div>\n </ListItem>\n <ListItem\n icon=\"lock\"\n narrow\n onClick={() => onScreenSelect(\n hasPassword ? SettingsScreens.TwoFaEnabled : SettingsScreens.TwoFaDisabled,\n )}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('TwoStepVerification')}</span>\n <span className=\"subtitle\">{lang(hasPassword ? 'PasswordOn' : 'PasswordOff')}</span>\n </div>\n </ListItem>\n <ListItem\n icon=\"active-sessions\"\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyActiveSessions)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('SessionsTitle')}</span>\n {sessionsCount > 0 && (\n <span className=\"subtitle\">\n {sessionsCount === 1 ? '1 session' : `${sessionsCount} sessions`}\n </span>\n )}\n </div>\n </ListItem>\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header mb-4\">{lang('PrivacyTitle')}</h4>\n\n <ListItem\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneNumber)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('PrivacyPhoneTitle')}</span>\n <span className=\"subtitle\">{getVisibilityValue(visibilityPrivacyPhoneNumber)}</span>\n </div>\n </ListItem>\n <ListItem\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyLastSeen)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('LastSeenTitle')}</span>\n <span className=\"subtitle\">{getVisibilityValue(visibilityPrivacyLastSeen)}</span>\n </div>\n </ListItem>\n <ListItem\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyProfilePhoto)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('PrivacyProfilePhotoTitle')}</span>\n <span className=\"subtitle\">{getVisibilityValue(visibilityPrivacyProfilePhoto)}</span>\n </div>\n </ListItem>\n <ListItem\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyForwarding)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('PrivacyForwardsTitle')}</span>\n <span className=\"subtitle\">{getVisibilityValue(visibilityPrivacyForwarding)}</span>\n </div>\n </ListItem>\n <ListItem\n narrow\n onClick={() => onScreenSelect(SettingsScreens.PrivacyGroupChats)}\n >\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{lang('WhoCanAddMe')}</span>\n <span className=\"subtitle\">{getVisibilityValue(visibilityPrivacyGroupChats)}</span>\n </div>\n </ListItem>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n settings: {\n byKey: { hasPassword },\n privacy,\n },\n blocked,\n activeSessions,\n } = global;\n\n return {\n hasPassword,\n blockedCount: blocked.totalCount,\n sessionsCount: activeSessions.length,\n visibilityPrivacyPhoneNumber: privacy.phoneNumber && privacy.phoneNumber.visibility,\n visibilityPrivacyLastSeen: privacy.lastSeen && privacy.lastSeen.visibility,\n visibilityPrivacyProfilePhoto: privacy.profilePhoto && privacy.profilePhoto.visibility,\n visibilityPrivacyForwarding: privacy.forwards && privacy.forwards.visibility,\n visibilityPrivacyGroupChats: privacy.chatInvite && privacy.chatInvite.visibility,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadBlockedContacts', 'loadAuthorizations', 'loadPrivacySettings',\n ]),\n)(SettingsPrivacy));\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ISettings } from '../../../types';\nimport { ApiLanguage } from '../../../api/types';\n\nimport { setLanguage } from '../../../util/langProvider';\nimport { pick } from '../../../util/iteratees';\n\nimport RadioGroup from '../../ui/RadioGroup';\nimport Loading from '../../ui/Loading';\nimport useFlag from '../../../hooks/useFlag';\n\ntype StateProps = Pick<ISettings, 'languages' | 'language'>;\n\ntype DispatchProps = Pick<GlobalActions, 'loadLanguages' | 'setSettingOption'>;\n\nconst SettingsLanguage: FC<StateProps & DispatchProps> = ({\n languages,\n language,\n loadLanguages,\n setSettingOption,\n}) => {\n const [selectedLanguage, setSelectedLanguage] = useState<string>(language);\n const [isLoading, markIsLoading, unmarkIsLoading] = useFlag();\n\n // TODO Throttle\n useEffect(() => {\n loadLanguages();\n }, [loadLanguages]);\n\n const handleChange = useCallback((langCode: string) => {\n setSelectedLanguage(langCode);\n markIsLoading();\n\n setLanguage(langCode, () => {\n unmarkIsLoading();\n setSettingOption({ language: langCode });\n });\n }, [markIsLoading, unmarkIsLoading, setSettingOption]);\n\n const options = useMemo(() => {\n return languages ? buildOptions(languages) : undefined;\n }, [languages]);\n\n return (\n <div className=\"settings-content settings-item settings-language custom-scroll\">\n {options ? (\n <RadioGroup\n name=\"keyboard-send-settings\"\n options={options}\n selected={selectedLanguage}\n loadingOption={isLoading ? selectedLanguage : undefined}\n onChange={handleChange}\n />\n ) : (\n <Loading />\n )}\n </div>\n );\n};\n\nfunction buildOptions(languages: ApiLanguage[]) {\n return languages.map(({ langCode, nativeName, name }) => ({\n value: langCode,\n label: nativeName,\n subLabel: name,\n }));\n}\n\nexport default memo(withGlobal(\n (global): StateProps => {\n return {\n languages: global.settings.byKey.languages,\n language: global.settings.byKey.language,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadLanguages', 'setSettingOption',\n ]),\n)(SettingsLanguage));\n","import { ApiPrivacyKey, SettingsScreens } from '../../../../types';\n\nexport function getPrivacyKey(screen: SettingsScreens): ApiPrivacyKey | undefined {\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumber:\n case SettingsScreens.PrivacyPhoneNumberAllowedContacts:\n case SettingsScreens.PrivacyPhoneNumberDeniedContacts:\n return 'phoneNumber';\n case SettingsScreens.PrivacyLastSeen:\n case SettingsScreens.PrivacyLastSeenAllowedContacts:\n case SettingsScreens.PrivacyLastSeenDeniedContacts:\n return 'lastSeen';\n case SettingsScreens.PrivacyProfilePhoto:\n case SettingsScreens.PrivacyProfilePhotoAllowedContacts:\n case SettingsScreens.PrivacyProfilePhotoDeniedContacts:\n return 'profilePhoto';\n case SettingsScreens.PrivacyForwarding:\n case SettingsScreens.PrivacyForwardingAllowedContacts:\n case SettingsScreens.PrivacyForwardingDeniedContacts:\n return 'forwards';\n case SettingsScreens.PrivacyGroupChats:\n case SettingsScreens.PrivacyGroupChatsAllowedContacts:\n case SettingsScreens.PrivacyGroupChatsDeniedContacts:\n return 'chatInvite';\n }\n\n return undefined;\n}\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiChat, ApiUser } from '../../../api/types';\nimport { ApiPrivacySettings, SettingsScreens } from '../../../types';\n\nimport useLang from '../../../hooks/useLang';\nimport { pick } from '../../../util/iteratees';\n\nimport ListItem from '../../ui/ListItem';\nimport RadioGroup from '../../ui/RadioGroup';\nimport { getPrivacyKey } from './helper/privacy';\n\ntype OwnProps = {\n screen: SettingsScreens;\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = Partial<ApiPrivacySettings> & {\n chatsById?: Record<number, ApiChat>;\n usersById?: Record<number, ApiUser>;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setPrivacyVisibility'>;\n\nconst SettingsPrivacyVisibility: FC<OwnProps & StateProps & DispatchProps> = ({\n screen,\n onScreenSelect,\n visibility,\n allowUserIds,\n allowChatIds,\n blockUserIds,\n blockChatIds,\n chatsById,\n setPrivacyVisibility,\n}) => {\n const lang = useLang();\n\n const visibilityOptions = useMemo(() => {\n switch (screen) {\n case SettingsScreens.PrivacyProfilePhoto:\n case SettingsScreens.PrivacyGroupChats:\n return [\n { value: 'everybody', label: lang('P2PEverybody') },\n { value: 'contacts', label: lang('P2PContacts') },\n ];\n\n default:\n return [\n { value: 'everybody', label: lang('P2PEverybody') },\n { value: 'contacts', label: lang('P2PContacts') },\n { value: 'nobody', label: lang('P2PNobody') },\n ];\n }\n }, [lang, screen]);\n\n const exceptionLists = {\n shouldShowDenied: visibility !== 'nobody',\n shouldShowAllowed: visibility !== 'everybody',\n };\n\n const privacyKey = getPrivacyKey(screen);\n\n const headerText = useMemo(() => {\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumber:\n return lang('PrivacyPhoneTitle');\n case SettingsScreens.PrivacyLastSeen:\n return lang('LastSeenTitle');\n case SettingsScreens.PrivacyProfilePhoto:\n return lang('PrivacyProfilePhotoTitle');\n case SettingsScreens.PrivacyForwarding:\n return lang('PrivacyForwardsTitle');\n case SettingsScreens.PrivacyGroupChats:\n return lang('WhoCanAddMe');\n default:\n return undefined;\n }\n }, [lang, screen]);\n\n const descriptionText = useMemo(() => {\n switch (screen) {\n case SettingsScreens.PrivacyLastSeen:\n return lang('CustomHelp');\n default:\n return undefined;\n }\n }, [lang, screen]);\n\n const allowedContactsScreen = (() => {\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumber:\n return SettingsScreens.PrivacyPhoneNumberAllowedContacts;\n case SettingsScreens.PrivacyLastSeen:\n return SettingsScreens.PrivacyLastSeenAllowedContacts;\n case SettingsScreens.PrivacyProfilePhoto:\n return SettingsScreens.PrivacyProfilePhotoAllowedContacts;\n case SettingsScreens.PrivacyForwarding:\n return SettingsScreens.PrivacyForwardingAllowedContacts;\n default:\n return SettingsScreens.PrivacyGroupChatsAllowedContacts;\n }\n })();\n\n const deniedContactsScreen = (() => {\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumber:\n return SettingsScreens.PrivacyPhoneNumberDeniedContacts;\n case SettingsScreens.PrivacyLastSeen:\n return SettingsScreens.PrivacyLastSeenDeniedContacts;\n case SettingsScreens.PrivacyProfilePhoto:\n return SettingsScreens.PrivacyProfilePhotoDeniedContacts;\n case SettingsScreens.PrivacyForwarding:\n return SettingsScreens.PrivacyForwardingDeniedContacts;\n default:\n return SettingsScreens.PrivacyGroupChatsDeniedContacts;\n }\n })();\n\n const allowedCount = useMemo(() => {\n if (!allowUserIds || !allowChatIds || !chatsById) {\n return 0;\n }\n\n return allowChatIds.reduce((result, chatId) => {\n return result + (chatsById[chatId] ? chatsById[chatId].membersCount! : 0);\n }, allowUserIds.length);\n }, [allowChatIds, allowUserIds, chatsById]);\n\n const blockCount = useMemo(() => {\n if (!blockUserIds || !blockChatIds || !chatsById) {\n return 0;\n }\n\n return blockChatIds.reduce((result, chatId) => {\n return result + (chatsById[chatId] ? chatsById[chatId].membersCount! : 0);\n }, blockUserIds.length);\n }, [blockChatIds, blockUserIds, chatsById]);\n\n const handleVisibilityChange = useCallback((value) => {\n setPrivacyVisibility({\n privacyKey,\n visibility: value,\n });\n }, [privacyKey, setPrivacyVisibility]);\n\n return (\n <div className=\"settings-content custom-scroll\">\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header\">{headerText}</h4>\n\n <RadioGroup\n name={`visibility-${privacyKey}`}\n options={visibilityOptions}\n onChange={handleVisibilityChange}\n selected={visibility}\n />\n\n {descriptionText && (\n <p className=\"settings-item-description-larger\">{descriptionText}</p>\n )}\n </div>\n\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header mb-4\">{lang('PrivacyExceptions')}</h4>\n\n {exceptionLists.shouldShowAllowed && (\n <ListItem\n narrow\n icon=\"add-user\"\n onClick={() => { onScreenSelect(allowedContactsScreen); }}\n >\n <div className=\"multiline-menu-item full-size\">\n {allowedCount > 0 && <span className=\"date\">+{allowedCount}</span>}\n <span className=\"title\">{lang('AlwaysShareWith')}</span>\n <span className=\"subtitle\">{lang('EditAdminAddUsers')}</span>\n </div>\n </ListItem>\n )}\n {exceptionLists.shouldShowDenied && (\n <ListItem\n narrow\n icon=\"delete-user\"\n onClick={() => { onScreenSelect(deniedContactsScreen); }}\n >\n <div className=\"multiline-menu-item full-size\">\n {blockCount > 0 && <span className=\"date\">−{blockCount}</span>}\n <span className=\"title\">{lang('NeverShareWith')}</span>\n <span className=\"subtitle\">{lang('EditAdminAddUsers')}</span>\n </div>\n </ListItem>\n )}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { screen }): StateProps => {\n let privacySettings: ApiPrivacySettings | undefined;\n\n const {\n chats: { byId: chatsById },\n settings: { privacy },\n } = global;\n\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumber:\n privacySettings = privacy.phoneNumber;\n break;\n\n case SettingsScreens.PrivacyLastSeen:\n privacySettings = privacy.lastSeen;\n break;\n\n case SettingsScreens.PrivacyProfilePhoto:\n privacySettings = privacy.profilePhoto;\n break;\n\n case SettingsScreens.PrivacyForwarding:\n privacySettings = privacy.forwards;\n break;\n\n case SettingsScreens.PrivacyGroupChats:\n privacySettings = privacy.chatInvite;\n break;\n }\n\n if (!privacySettings) {\n return {};\n }\n\n return {\n ...privacySettings,\n chatsById,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['setPrivacyVisibility']),\n)(SettingsPrivacyVisibility));\n","import React, {\n FC, memo, useCallback, useEffect, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiSession } from '../../../api/types';\n\nimport { pick } from '../../../util/iteratees';\nimport { formatPastTimeShort } from '../../../util/dateFormat';\nimport useFlag from '../../../hooks/useFlag';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\ntype StateProps = {\n activeSessions: ApiSession[];\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'loadAuthorizations' | 'terminateAuthorization' | 'terminateAllAuthorizations'\n)>;\n\nconst SettingsPrivacyActiveSessions: FC<StateProps & DispatchProps> = ({\n activeSessions,\n loadAuthorizations,\n terminateAuthorization,\n terminateAllAuthorizations,\n}) => {\n const [isConfirmTerminateAllDialogOpen, openConfirmTerminateAllDialog, closeConfirmTerminateAllDialog] = useFlag();\n useEffect(() => {\n loadAuthorizations();\n }, [loadAuthorizations]);\n\n const handleTerminateSessionClick = useCallback((hash: string) => {\n terminateAuthorization({ hash });\n }, [terminateAuthorization]);\n\n const handleTerminateAllSessions = useCallback(() => {\n closeConfirmTerminateAllDialog();\n terminateAllAuthorizations();\n }, [closeConfirmTerminateAllDialog, terminateAllAuthorizations]);\n\n const currentSession = useMemo(() => {\n return activeSessions.find((session) => session.isCurrent);\n }, [activeSessions]);\n\n const otherSessions = useMemo(() => {\n return activeSessions.filter((session) => !session.isCurrent);\n }, [activeSessions]);\n\n const lang = useLang();\n\n function renderCurrentSession(session: ApiSession) {\n return (\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header mb-4\">{lang('AuthSessions.CurrentSession')}</h4>\n\n <ListItem narrow inactive>\n <div className=\"multiline-menu-item\">\n <span className=\"title\">{session.appName}</span>\n <span className=\"subtitle black tight\">{getDeviceEnvironment(session)}</span>\n <span className=\"subtitle\">{session.ip} - {getLocation(session)}</span>\n </div>\n </ListItem>\n\n <ListItem\n className=\"destructive mb-0\"\n icon=\"stop\"\n ripple\n narrow\n onClick={openConfirmTerminateAllDialog}\n >\n {lang('TerminateAllSessions')}\n </ListItem>\n </div>\n );\n }\n\n function renderOtherSessions(sessions: ApiSession[]) {\n return (\n <div className=\"settings-item\">\n <h4 className=\"settings-item-header mb-4\">Other Sessions</h4>\n\n {sessions.map(renderSession)}\n </div>\n );\n }\n\n function renderSession(session: ApiSession) {\n return (\n <ListItem\n key={session.hash}\n ripple\n narrow\n contextActions={[{\n title: 'Terminate',\n icon: 'stop',\n handler: () => {\n handleTerminateSessionClick(session.hash);\n },\n }]}\n >\n <div className=\"multiline-menu-item full-size\">\n <span className=\"date\">{formatPastTimeShort(session.dateActive * 1000)}</span>\n <span className=\"title\">{session.appName}</span>\n <span className=\"subtitle black tight\">{getDeviceEnvironment(session)}</span>\n <span className=\"subtitle\">{session.ip} - {getLocation(session)}</span>\n </div>\n </ListItem>\n );\n }\n\n return (\n <div className=\"settings-content custom-scroll\">\n {currentSession && renderCurrentSession(currentSession)}\n\n {otherSessions && renderOtherSessions(otherSessions)}\n\n {otherSessions && (\n <ConfirmDialog\n isOpen={isConfirmTerminateAllDialogOpen}\n onClose={closeConfirmTerminateAllDialog}\n text=\"Are you sure you want to terminate all other sessions?\"\n confirmLabel=\"Terminate All Other Sessions\"\n confirmHandler={handleTerminateAllSessions}\n confirmIsDestructive\n />\n )};\n </div>\n );\n};\n\nfunction getLocation(session: ApiSession) {\n return [session.region, session.country].filter(Boolean).join(', ');\n}\n\nfunction getDeviceEnvironment(session: ApiSession) {\n return `${session.deviceModel}${session.deviceModel ? ', ' : ''} ${session.platform} ${session.systemVersion}`;\n}\n\nexport default memo(withGlobal(\n (global): StateProps => ({ activeSessions: global.activeSessions }),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadAuthorizations', 'terminateAuthorization', 'terminateAllAuthorizations',\n ]),\n)(SettingsPrivacyActiveSessions));\n","import React, {\n FC, memo, useCallback,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiChat, ApiUser } from '../../../api/types';\n\nimport { CHAT_HEIGHT_PX } from '../../../config';\nimport { formatPhoneNumberWithCode } from '../../../util/phoneNumber';\nimport { pick } from '../../../util/iteratees';\nimport {\n getChatTitle, getUserFullName, isChatPrivate,\n} from '../../../modules/helpers';\nimport renderText from '../../common/helpers/renderText';\nimport buildClassName from '../../../util/buildClassName';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Avatar from '../../common/Avatar';\nimport Loading from '../../ui/Loading';\n\ntype StateProps = {\n chatsByIds: Record<number, ApiChat>;\n usersByIds: Record<number, ApiUser>;\n blockedIds: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'unblockContact'>;\n\nconst SettingsPrivacyBlockedUsers: FC<StateProps & DispatchProps> = ({\n chatsByIds,\n usersByIds,\n blockedIds,\n unblockContact,\n}) => {\n const handleUnblockClick = useCallback((contactId: number) => {\n unblockContact({ contactId });\n }, [unblockContact]);\n\n const lang = useLang();\n\n function renderContact(contactId: number, i: number, viewportOffset: number) {\n const isPrivate = isChatPrivate(contactId);\n const user = isPrivate ? usersByIds[contactId] : undefined;\n const chat = !isPrivate ? chatsByIds[contactId] : undefined;\n\n const className = buildClassName(\n 'Chat chat-item-clickable blocked-list-item',\n isPrivate ? 'private' : 'group',\n );\n\n return (\n <ListItem\n key={contactId}\n className={className}\n ripple\n narrow\n contextActions={[{\n title: 'Unblock',\n icon: 'unlock',\n handler: () => {\n handleUnblockClick(contactId);\n },\n }]}\n style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}\n >\n <Avatar size=\"medium\" user={user} chat={chat} />\n <div className=\"contact-info\">\n <h3>{renderText((isPrivate ? getUserFullName(user) : getChatTitle(chat!)) || '')}</h3>\n {user && user.phoneNumber && (\n <div className=\"contact-phone\">{formatPhoneNumberWithCode(user.phoneNumber)}</div>\n )}\n {user && !user.phoneNumber && user.username && (\n <div className=\"contact-username\">@{user.username}</div>\n )}\n </div>\n </ListItem>\n );\n }\n\n return (\n <div className=\"settings-fab-wrapper\">\n <div className=\"settings-content infinite-scroll\">\n <div className=\"settings-item\">\n <p className=\"settings-item-description-larger mt-0 mb-2\">\n {lang('BlockedUsersInfo')}\n </p>\n </div>\n\n <div className=\"chat-list custom-scroll\">\n {blockedIds && blockedIds.length ? (\n <div className=\"scroll-container\">\n {blockedIds!.map((contactId, i) => renderContact(contactId, i, 0))}\n </div>\n ) : blockedIds && !blockedIds.length ? (\n <div className=\"no-results\">\n List is empty\n </div>\n ) : (\n <Loading key=\"loading\" />\n )}\n </div>\n </div>\n\n <FloatingActionButton\n isShown\n onClick={() => {\n }}\n className=\"not-implemented\"\n ariaLabel=\"Add a blocked user\"\n >\n <i className=\"icon-add\" />\n </FloatingActionButton>\n </div>\n );\n};\n\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const {\n chats: {\n byId: chatsByIds,\n },\n users: {\n byId: usersByIds,\n },\n blocked: {\n ids,\n },\n } = global;\n\n return {\n chatsByIds,\n usersByIds,\n blockedIds: ids,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['unblockContact']),\n)(SettingsPrivacyBlockedUsers));\n","import React, { FC, memo } from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../../api/types';\nimport { SettingsScreens } from '../../../../types';\n\nimport { selectAnimatedEmoji } from '../../../../modules/selectors';\nimport useLang from '../../../../hooks/useLang';\n\nimport ListItem from '../../../ui/ListItem';\nimport AnimatedEmoji from '../../../common/AnimatedEmoji';\nimport renderText from '../../../common/helpers/renderText';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n animatedEmoji: ApiSticker;\n};\n\nconst SettingsTwoFaEnabled: FC<OwnProps & StateProps> = ({\n animatedEmoji, onScreenSelect,\n}) => {\n const lang = useLang();\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <AnimatedEmoji sticker={animatedEmoji} />\n\n <p className=\"settings-item-description mb-3\">\n {renderText(lang('EnabledPasswordText'), ['br'])}\n </p>\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <ListItem\n icon=\"edit\"\n onClick={() => onScreenSelect(SettingsScreens.TwoFaChangePasswordCurrent)}\n >\n {lang('ChangePassword')}\n </ListItem>\n <ListItem\n icon=\"password-off\"\n onClick={() => onScreenSelect(SettingsScreens.TwoFaTurnOff)}\n >\n {lang('TurnPasswordOff')}\n </ListItem>\n <ListItem\n icon=\"email\"\n onClick={() => onScreenSelect(SettingsScreens.TwoFaRecoveryEmailCurrentPassword)}\n >\n {lang('SetRecoveryEmail')}\n </ListItem>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>((global) => {\n return {\n animatedEmoji: selectAnimatedEmoji(global, '🔐'),\n };\n})(SettingsTwoFaEnabled));\n","import React, {\n FC, memo, useCallback, useState,\n} from '../../../../lib/teact/teact';\n\nimport useLang from '../../../../hooks/useLang';\n\nimport PasswordMonkey from '../../../common/PasswordMonkey';\nimport PasswordForm from '../../../common/PasswordForm';\n\ntype OwnProps = {\n error?: string;\n isLoading?: boolean;\n expectedPassword?: string;\n placeholder?: string;\n hint?: string;\n submitLabel?: string;\n clearError?: NoneToVoidFunction;\n onSubmit: (password: string) => void;\n};\n\nconst EQUAL_PASSWORD_ERROR = 'Passwords Should Be Equal';\n\nconst SettingsTwoFaPassword: FC<OwnProps> = ({\n error,\n isLoading,\n expectedPassword,\n placeholder = 'Current Password',\n hint,\n submitLabel,\n clearError,\n onSubmit,\n}) => {\n const [validationError, setValidationError] = useState<string>('');\n const [shouldShowPassword, setShouldShowPassword] = useState(false);\n\n const handleSubmit = useCallback((newPassword) => {\n if (expectedPassword && newPassword !== expectedPassword) {\n setValidationError(EQUAL_PASSWORD_ERROR);\n } else {\n onSubmit(newPassword);\n }\n }, [onSubmit, expectedPassword]);\n\n const handleClearError = useCallback(() => {\n if (clearError) {\n clearError();\n }\n setValidationError('');\n }, [clearError]);\n\n const lang = useLang();\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <PasswordMonkey isBig isPasswordVisible={shouldShowPassword} />\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <PasswordForm\n error={validationError || error}\n hint={hint}\n placeholder={placeholder}\n submitLabel={submitLabel || lang('Next')}\n clearError={handleClearError}\n isLoading={isLoading}\n isPasswordVisible={shouldShowPassword}\n onChangePasswordVisibility={setShouldShowPassword}\n onSubmit={handleSubmit}\n />\n </div>\n </div>\n );\n};\n\nexport default memo(SettingsTwoFaPassword);\n","import React, { FC, memo } from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../../api/types';\n\nimport { selectAnimatedEmoji } from '../../../../modules/selectors';\nimport useLang from '../../../../hooks/useLang';\n\nimport Button from '../../../ui/Button';\nimport AnimatedEmoji from '../../../common/AnimatedEmoji';\n\ntype OwnProps = {\n onStart: NoneToVoidFunction;\n};\n\ntype StateProps = {\n animatedEmoji: ApiSticker;\n};\n\nconst SettingsTwoFaStart: FC<OwnProps & StateProps> = ({ animatedEmoji, onStart }) => {\n const lang = useLang();\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <AnimatedEmoji sticker={animatedEmoji} />\n\n <p className=\"settings-item-description mb-3\">\n {lang('SetAdditionalPasswordInfo')}\n </p>\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <Button onClick={onStart}>{lang('EditAdminTransferSetPassword')}</Button>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>((global) => {\n return {\n animatedEmoji: selectAnimatedEmoji(global, '🔐'),\n };\n})(SettingsTwoFaStart));\n","import React, {\n FC, memo, useEffect, useRef, useState,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../../api/types';\n\nimport { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../../util/environment';\nimport { selectAnimatedEmoji } from '../../../../modules/selectors';\nimport useFlag from '../../../../hooks/useFlag';\nimport useLang from '../../../../hooks/useLang';\n\nimport Button from '../../../ui/Button';\nimport Modal from '../../../ui/Modal';\nimport AnimatedEmoji from '../../../common/AnimatedEmoji';\nimport InputText from '../../../ui/InputText';\nimport renderText from '../../../common/helpers/renderText';\n\ntype OwnProps = {\n icon: 'hint' | 'email';\n type?: 'text' | 'email';\n isLoading?: boolean;\n error?: string;\n placeholder: string;\n shouldConfirm?: boolean;\n clearError?: NoneToVoidFunction;\n onSubmit: (value?: string) => void;\n};\n\ntype StateProps = {\n animatedEmoji: ApiSticker;\n};\n\nconst FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400;\n\nconst SettingsTwoFaSkippableForm: FC<OwnProps & StateProps> = ({\n animatedEmoji,\n type = 'text',\n isLoading,\n error,\n placeholder,\n shouldConfirm,\n clearError,\n onSubmit,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [value, setValue] = useState<string>('');\n const [isConfirmShown, markIsConfirmShown, unmarkIsConfirmShown] = useFlag(false);\n\n useEffect(() => {\n if (!IS_TOUCH_ENV) {\n setTimeout(() => {\n inputRef.current!.focus();\n }, FOCUS_DELAY_TIMEOUT_MS);\n }\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (error && clearError) {\n clearError();\n }\n\n setValue(e.target.value);\n };\n\n const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n\n if (!inputRef.current) {\n return;\n }\n\n onSubmit(value);\n };\n\n const handleSkip = () => {\n onSubmit();\n };\n\n const handleSkipConfirm = () => {\n unmarkIsConfirmShown();\n onSubmit();\n };\n\n const lang = useLang();\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <AnimatedEmoji sticker={animatedEmoji} />\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <form action=\"\" onSubmit={handleSubmit}>\n <InputText\n ref={inputRef}\n value={value}\n inputMode={type}\n label={placeholder}\n error={error}\n onChange={handleInputChange}\n />\n\n {value ? (\n <Button type=\"submit\" isLoading={isLoading} ripple>{lang('Continue')}</Button>\n ) : (\n <Button\n isText\n isLoading={isLoading}\n ripple\n onClick={shouldConfirm ? markIsConfirmShown : handleSkip}\n >\n {lang('YourEmailSkip')}\n </Button>\n )}\n </form>\n {shouldConfirm && (\n <Modal\n className=\"narrow\"\n isOpen={isConfirmShown}\n title={lang('YourEmailSkipWarning')}\n onClose={unmarkIsConfirmShown}\n >\n {renderText(lang('YourEmailSkipWarningText'), ['br', 'simple_markdown'])}\n <div className=\"dialog-buttons\">\n <Button\n color=\"danger\"\n ripple\n isText\n className=\"confirm-dialog-button\"\n onClick={handleSkipConfirm}\n >\n {lang('YourEmailSkip')}\n </Button>\n <Button\n color=\"primary\"\n ripple\n isText\n className=\"confirm-dialog-button\"\n onClick={unmarkIsConfirmShown}\n >\n {lang('Cancel')}\n </Button>\n </div>\n </Modal>\n )}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>((global, { icon }) => {\n return {\n animatedEmoji: selectAnimatedEmoji(global, icon === 'email' ? '💌' : '💡'),\n };\n})(SettingsTwoFaSkippableForm));\n","import React, { FC, memo } from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../../api/types';\nimport { SettingsScreens } from '../../../../types';\n\nimport { selectAnimatedEmoji } from '../../../../modules/selectors';\nimport useLang from '../../../../hooks/useLang';\n\nimport Button from '../../../ui/Button';\nimport AnimatedEmoji from '../../../common/AnimatedEmoji';\n\ntype OwnProps = {\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n animatedEmoji: ApiSticker;\n};\n\nconst SettingsTwoFaCongratulations: FC<OwnProps & StateProps> = ({\n animatedEmoji, onScreenSelect,\n}) => {\n const lang = useLang();\n\n const handleClick = () => {\n onScreenSelect(SettingsScreens.Privacy);\n };\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <AnimatedEmoji sticker={animatedEmoji} />\n\n <p className=\"settings-item-description mb-3\">\n {lang('TwoStepVerificationPasswordSetInfo')}\n </p>\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <Button onClick={handleClick}>{lang('TwoStepVerificationPasswordReturnSettings')}</Button>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>((global) => {\n return {\n animatedEmoji: selectAnimatedEmoji(global, '🥳'),\n };\n})(SettingsTwoFaCongratulations));\n","import React, {\n FC, memo, useEffect, useRef, useState,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../../api/types';\n\nimport { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../../util/environment';\nimport { selectAnimatedEmoji } from '../../../../modules/selectors';\nimport useLang from '../../../../hooks/useLang';\n\nimport AnimatedEmoji from '../../../common/AnimatedEmoji';\nimport InputText from '../../../ui/InputText';\nimport Loading from '../../../ui/Loading';\n\ntype OwnProps = {\n isLoading?: boolean;\n error?: string;\n clearError: NoneToVoidFunction;\n onSubmit: (hint: string) => void;\n};\n\ntype StateProps = {\n animatedEmoji: ApiSticker;\n codeLength: number;\n};\n\nconst FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400;\n\nconst SettingsTwoFaEmailCode: FC<OwnProps & StateProps> = ({\n animatedEmoji,\n codeLength,\n isLoading,\n error,\n clearError,\n onSubmit,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [value, setValue] = useState<string>('');\n\n useEffect(() => {\n if (!IS_TOUCH_ENV) {\n setTimeout(() => {\n inputRef.current!.focus();\n }, FOCUS_DELAY_TIMEOUT_MS);\n }\n }, []);\n\n const lang = useLang();\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (error && clearError) {\n clearError();\n }\n\n const newValue = e.target.value.slice(0, codeLength);\n\n if (newValue.length === codeLength) {\n onSubmit(newValue);\n }\n\n setValue(newValue);\n e.target.value = newValue;\n };\n\n return (\n <div className=\"settings-content two-fa custom-scroll\">\n <div className=\"settings-content-header\">\n <AnimatedEmoji sticker={animatedEmoji} />\n </div>\n\n <div className=\"settings-item pt-0 no-border\">\n <InputText\n value={value}\n ref={inputRef}\n inputMode=\"decimal\"\n label={lang('YourEmailCode')}\n error={error}\n onChange={handleInputChange}\n />\n {isLoading && <Loading />}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>((global) => {\n return {\n animatedEmoji: selectAnimatedEmoji(global, '💌'),\n codeLength: global.twoFaSettings.waitingEmailCodeLength,\n };\n})(SettingsTwoFaEmailCode));\n","import React, {\n FC, memo, useCallback, useEffect,\n} from '../../../../lib/teact/teact';\nimport { withGlobal } from '../../../../lib/teact/teactn';\n\nimport { GlobalActions, GlobalState } from '../../../../global/types';\nimport { SettingsScreens } from '../../../../types';\n\nimport { pick } from '../../../../util/iteratees';\nimport { TwoFaDispatch, TwoFaState } from '../../../../hooks/reducers/useTwoFaReducer';\nimport useLang from '../../../../hooks/useLang';\n\nimport SettingsTwoFaEnabled from './SettingsTwoFaEnabled';\nimport SettingsTwoFaPassword from './SettingsTwoFaPassword';\nimport SettingsTwoFaStart from './SettingsTwoFaStart';\nimport SettingsTwoFaSkippableForm from './SettingsTwoFaSkippableForm';\nimport SettingsTwoFaCongratulations from './SettingsTwoFaCongratulations';\nimport SettingsTwoFaEmailCode from './SettingsTwoFaEmailCode';\n\nexport type OwnProps = {\n state: TwoFaState;\n currentScreen: SettingsScreens;\n dispatch: TwoFaDispatch;\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = GlobalState['twoFaSettings'];\n\ntype DispatchProps = Pick<GlobalActions, (\n 'updatePassword' | 'updateRecoveryEmail' | 'clearPassword' | 'provideTwoFaEmailCode' |\n 'checkPassword' | 'clearTwoFaError'\n)>;\n\nconst SettingsTwoFa: FC<OwnProps & StateProps & DispatchProps> = ({\n currentScreen,\n state,\n hint,\n isLoading,\n error,\n waitingEmailCodeLength,\n dispatch,\n onScreenSelect,\n updatePassword,\n checkPassword,\n clearTwoFaError,\n updateRecoveryEmail,\n provideTwoFaEmailCode,\n clearPassword,\n}) => {\n useEffect(() => {\n if (waitingEmailCodeLength) {\n if (currentScreen === SettingsScreens.TwoFaNewPasswordEmail) {\n onScreenSelect(SettingsScreens.TwoFaNewPasswordEmailCode);\n } else if (currentScreen === SettingsScreens.TwoFaRecoveryEmail) {\n onScreenSelect(SettingsScreens.TwoFaRecoveryEmailCode);\n }\n }\n }, [currentScreen, onScreenSelect, waitingEmailCodeLength]);\n\n const handleStartWizard = useCallback(() => {\n dispatch({ type: 'reset' });\n onScreenSelect(SettingsScreens.TwoFaNewPassword);\n }, [dispatch, onScreenSelect]);\n\n const handleNewPassword = useCallback((value: string) => {\n dispatch({ type: 'setPassword', payload: value });\n onScreenSelect(SettingsScreens.TwoFaNewPasswordConfirm);\n }, [dispatch, onScreenSelect]);\n\n const handleNewPasswordConfirm = useCallback(() => {\n onScreenSelect(SettingsScreens.TwoFaNewPasswordHint);\n }, [onScreenSelect]);\n\n const handleNewPasswordHint = useCallback((value?: string) => {\n dispatch({ type: 'setHint', payload: value });\n onScreenSelect(SettingsScreens.TwoFaNewPasswordEmail);\n }, [dispatch, onScreenSelect]);\n\n const handleNewPasswordEmail = useCallback((value?: string) => {\n dispatch({ type: 'setEmail', payload: value });\n updatePassword({\n ...state,\n email: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.TwoFaCongratulations);\n },\n });\n }, [dispatch, onScreenSelect, state, updatePassword]);\n\n const handleChangePasswordCurrent = useCallback((value: string) => {\n dispatch({ type: 'setCurrentPassword', payload: value });\n checkPassword({\n currentPassword: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.TwoFaChangePasswordNew);\n },\n });\n }, [checkPassword, dispatch, onScreenSelect]);\n\n const handleChangePasswordNew = useCallback((value: string) => {\n dispatch({ type: 'setPassword', payload: value });\n onScreenSelect(SettingsScreens.TwoFaChangePasswordConfirm);\n }, [dispatch, onScreenSelect]);\n\n const handleChangePasswordConfirm = useCallback(() => {\n onScreenSelect(SettingsScreens.TwoFaChangePasswordHint);\n }, [onScreenSelect]);\n\n const handleChangePasswordHint = useCallback((value?: string) => {\n dispatch({ type: 'setHint', payload: value });\n updatePassword({\n ...state,\n hint: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.TwoFaCongratulations);\n },\n });\n }, [dispatch, onScreenSelect, state, updatePassword]);\n\n const handleTurnOff = useCallback((value: string) => {\n clearPassword({\n currentPassword: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.Privacy);\n },\n });\n }, [clearPassword, onScreenSelect]);\n\n const handleRecoveryEmailCurrentPassword = useCallback((value: string) => {\n dispatch({ type: 'setCurrentPassword', payload: value });\n checkPassword({\n currentPassword: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.TwoFaRecoveryEmail);\n },\n });\n }, [checkPassword, dispatch, onScreenSelect]);\n\n const handleRecoveryEmail = useCallback((value?: string) => {\n dispatch({ type: 'setEmail', payload: value });\n updateRecoveryEmail({\n ...state,\n email: value,\n onSuccess: () => {\n onScreenSelect(SettingsScreens.TwoFaCongratulations);\n },\n });\n }, [dispatch, onScreenSelect, state, updateRecoveryEmail]);\n\n const handleEmailCode = useCallback((code: string) => {\n provideTwoFaEmailCode({ code });\n }, [provideTwoFaEmailCode]);\n\n const lang = useLang();\n\n switch (currentScreen) {\n case SettingsScreens.TwoFaDisabled:\n return (\n <SettingsTwoFaStart\n onStart={handleStartWizard}\n />\n );\n\n case SettingsScreens.TwoFaNewPassword:\n return (\n <SettingsTwoFaPassword\n placeholder={lang('EnterPassword')}\n submitLabel={lang('Continue')}\n onSubmit={handleNewPassword}\n />\n );\n\n case SettingsScreens.TwoFaNewPasswordConfirm:\n return (\n <SettingsTwoFaPassword\n expectedPassword={state.password}\n placeholder={lang('PleaseReEnterPassword')}\n submitLabel={lang('Continue')}\n onSubmit={handleNewPasswordConfirm}\n />\n );\n\n case SettingsScreens.TwoFaNewPasswordHint:\n return (\n <SettingsTwoFaSkippableForm\n icon=\"hint\"\n placeholder={lang('PasswordHintPlaceholder')}\n onSubmit={handleNewPasswordHint}\n />\n );\n\n case SettingsScreens.TwoFaNewPasswordEmail:\n return (\n <SettingsTwoFaSkippableForm\n icon=\"email\"\n type=\"email\"\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n placeholder={lang('RecoveryEmailTitle')}\n shouldConfirm\n onSubmit={handleNewPasswordEmail}\n />\n );\n\n case SettingsScreens.TwoFaNewPasswordEmailCode:\n return (\n <SettingsTwoFaEmailCode\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n onSubmit={handleEmailCode}\n />\n );\n\n case SettingsScreens.TwoFaCongratulations:\n return (\n <SettingsTwoFaCongratulations\n onScreenSelect={onScreenSelect}\n />\n );\n\n case SettingsScreens.TwoFaEnabled:\n return (\n <SettingsTwoFaEnabled\n onScreenSelect={onScreenSelect}\n />\n );\n\n case SettingsScreens.TwoFaChangePasswordCurrent:\n return (\n <SettingsTwoFaPassword\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n hint={hint}\n onSubmit={handleChangePasswordCurrent}\n />\n );\n\n case SettingsScreens.TwoFaChangePasswordNew:\n return (\n <SettingsTwoFaPassword\n placeholder={lang('PleaseEnterNewFirstPassword')}\n onSubmit={handleChangePasswordNew}\n />\n );\n\n case SettingsScreens.TwoFaChangePasswordConfirm:\n return (\n <SettingsTwoFaPassword\n expectedPassword={state.password}\n placeholder={lang('PleaseReEnterPassword')}\n onSubmit={handleChangePasswordConfirm}\n />\n );\n\n case SettingsScreens.TwoFaChangePasswordHint:\n return (\n <SettingsTwoFaSkippableForm\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n icon=\"hint\"\n placeholder={lang('PasswordHintPlaceholder')}\n onSubmit={handleChangePasswordHint}\n />\n );\n\n case SettingsScreens.TwoFaTurnOff:\n return (\n <SettingsTwoFaPassword\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n hint={hint}\n onSubmit={handleTurnOff}\n />\n );\n\n case SettingsScreens.TwoFaRecoveryEmailCurrentPassword:\n return (\n <SettingsTwoFaPassword\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n hint={hint}\n onSubmit={handleRecoveryEmailCurrentPassword}\n />\n );\n\n case SettingsScreens.TwoFaRecoveryEmail:\n return (\n <SettingsTwoFaSkippableForm\n icon=\"email\"\n type=\"email\"\n placeholder={lang('RecoveryEmailTitle')}\n onSubmit={handleRecoveryEmail}\n />\n );\n\n case SettingsScreens.TwoFaRecoveryEmailCode:\n return (\n <SettingsTwoFaEmailCode\n isLoading={isLoading}\n error={error}\n clearError={clearTwoFaError}\n onSubmit={handleEmailCode}\n />\n );\n\n default:\n return undefined;\n }\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => ({ ...global.twoFaSettings }),\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'updatePassword', 'updateRecoveryEmail', 'clearPassword', 'provideTwoFaEmailCode',\n 'checkPassword', 'clearTwoFaError',\n ]),\n)(SettingsTwoFa));\n","import React, {\n FC, useCallback, useRef, useEffect, memo,\n} from '../../lib/teact/teact';\n\nimport { isChatPrivate } from '../../modules/helpers';\n\nimport InfiniteScroll from '../ui/InfiniteScroll';\nimport Checkbox from '../ui/Checkbox';\nimport InputText from '../ui/InputText';\nimport ListItem from '../ui/ListItem';\nimport PrivateChatInfo from './PrivateChatInfo';\nimport GroupChatInfo from './GroupChatInfo';\nimport PickerSelectedItem from './PickerSelectedItem';\nimport useInfiniteScroll from '../../hooks/useInfiniteScroll';\nimport useLang from '../../hooks/useLang';\n\nimport Loading from '../ui/Loading';\n\nimport './Picker.scss';\n\ntype OwnProps = {\n itemIds: number[];\n selectedIds: number[];\n filterValue?: string;\n filterPlaceholder?: string;\n notFoundText?: string;\n searchInputId?: string;\n isLoading?: boolean;\n onSelectedIdsChange: (ids: number[]) => void;\n onFilterChange: (value: string) => void;\n onLoadMore?: () => void;\n};\n\n// Focus slows down animation, also it breaks transition layout in Chrome\nconst FOCUS_DELAY_MS = 500;\n\nconst MAX_FULL_ITEMS = 10;\nconst ALWAYS_FULL_ITEMS_COUNT = 5;\n\nconst Picker: FC<OwnProps> = ({\n itemIds,\n selectedIds,\n filterValue,\n filterPlaceholder,\n notFoundText,\n searchInputId,\n isLoading,\n onSelectedIdsChange,\n onFilterChange,\n onLoadMore,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n const shouldMinimize = selectedIds.length > MAX_FULL_ITEMS;\n\n useEffect(() => {\n setTimeout(() => {\n requestAnimationFrame(() => {\n inputRef.current!.focus();\n });\n }, FOCUS_DELAY_MS);\n }, []);\n\n const handleItemClick = useCallback((id: number) => {\n const newSelectedIds = [...selectedIds];\n if (newSelectedIds.includes(id)) {\n newSelectedIds.splice(newSelectedIds.indexOf(id), 1);\n } else {\n newSelectedIds.push(id);\n }\n onSelectedIdsChange(newSelectedIds);\n onFilterChange('');\n }, [selectedIds, onSelectedIdsChange, onFilterChange]);\n\n const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { value } = e.currentTarget;\n onFilterChange(value);\n }, [onFilterChange]);\n\n const [viewportIds, getMore] = useInfiniteScroll(onLoadMore, itemIds, Boolean(filterValue));\n\n const lang = useLang();\n\n return (\n <div className=\"Picker\">\n <div className=\"picker-header custom-scroll\">\n {selectedIds.map((id, i) => (\n <PickerSelectedItem\n chatOrUserId={id}\n isMinimized={shouldMinimize && i < selectedIds.length - ALWAYS_FULL_ITEMS_COUNT}\n canClose\n onClick={handleItemClick}\n clickArg={id}\n />\n ))}\n <InputText\n id={searchInputId}\n ref={inputRef}\n value={filterValue}\n onChange={handleFilterChange}\n placeholder={filterPlaceholder || lang('SelectChat')}\n />\n </div>\n\n {viewportIds && viewportIds.length ? (\n <InfiniteScroll\n className=\"picker-list custom-scroll\"\n items={viewportIds}\n onLoadMore={getMore}\n >\n {viewportIds.map((id) => (\n <ListItem\n key={id}\n className=\"chat-item-clickable picker-list-item\"\n onClick={() => handleItemClick(id)}\n ripple\n >\n <Checkbox label=\"\" checked={selectedIds.includes(id)} />\n {isChatPrivate(id) ? (\n <PrivateChatInfo userId={id} />\n ) : (\n <GroupChatInfo chatId={id} />\n )}\n </ListItem>\n ))}\n </InfiniteScroll>\n ) : !isLoading && viewportIds && !viewportIds.length ? (\n <p className=\"no-results\">{notFoundText || 'Sorry, nothing found.'}</p>\n ) : (\n <Loading />\n )}\n </div>\n );\n};\n\nexport default memo(Picker);\n","import React, {\n FC, memo, useCallback, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions, GlobalState } from '../../../global/types';\nimport { ApiChat } from '../../../api/types';\nimport { ApiPrivacySettings, SettingsScreens } from '../../../types';\n\nimport useLang from '../../../hooks/useLang';\nimport { pick } from '../../../util/iteratees';\nimport searchWords from '../../../util/searchWords';\nimport { getPrivacyKey } from './helper/privacy';\nimport {\n getChatTitle, isChatGroup, isChatPrivate, prepareChatList,\n} from '../../../modules/helpers';\n\nimport Picker from '../../common/Picker';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\n\nexport type OwnProps = {\n isAllowList?: boolean;\n screen: SettingsScreens;\n onScreenSelect: (screen: SettingsScreens) => void;\n};\n\ntype StateProps = {\n currentUserId?: number;\n chatsById: Record<number, ApiChat>;\n listIds?: number[];\n orderedPinnedIds?: number[];\n archivedListIds?: number[];\n archivedPinnedIds?: number[];\n settings?: ApiPrivacySettings;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'setPrivacySettings'>;\n\nconst SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & DispatchProps> = ({\n currentUserId,\n isAllowList,\n screen,\n settings,\n chatsById,\n listIds,\n orderedPinnedIds,\n archivedListIds,\n archivedPinnedIds,\n setPrivacySettings,\n onScreenSelect,\n}) => {\n const selectedContactIds = useMemo(() => {\n if (!settings) {\n return [];\n }\n\n if (isAllowList) {\n return [...settings.allowUserIds, ...settings.allowChatIds];\n } else {\n return [...settings.blockUserIds, ...settings.blockChatIds];\n }\n }, [isAllowList, settings]);\n const [searchQuery, setSearchQuery] = useState<string>('');\n const [isSubmitShown, setIsSubmitShown] = useState<boolean>(false);\n const [newSelectedContactIds, setNewSelectedContactIds] = useState<number[]>(selectedContactIds);\n\n const chats = useMemo(() => {\n const activeChatArrays = listIds\n ? prepareChatList(chatsById, listIds, orderedPinnedIds, 'all')\n : undefined;\n const archivedChatArrays = archivedListIds\n ? prepareChatList(chatsById, archivedListIds, archivedPinnedIds, 'archived')\n : undefined;\n\n if (!activeChatArrays && !archivedChatArrays) {\n return undefined;\n }\n\n return [\n ...(activeChatArrays\n ? [\n ...activeChatArrays.pinnedChats,\n ...activeChatArrays.otherChats,\n ]\n : []\n ),\n ...(archivedChatArrays ? archivedChatArrays.otherChats : []),\n ];\n }, [chatsById, listIds, orderedPinnedIds, archivedListIds, archivedPinnedIds]);\n\n const displayedIds = useMemo(() => {\n if (!chats) {\n return undefined;\n }\n\n return chats\n .filter((chat) => (\n ((isChatPrivate(chat.id) && chat.id !== currentUserId) || isChatGroup(chat))\n && (\n !searchQuery\n || searchWords(getChatTitle(chat), searchQuery)\n || selectedContactIds.includes(chat.id)\n )\n ))\n .map(({ id }) => id);\n }, [chats, currentUserId, searchQuery, selectedContactIds]);\n\n const handleSelectedContactIdsChange = useCallback((value: number[]) => {\n setNewSelectedContactIds(value);\n setIsSubmitShown(true);\n }, []);\n\n const handleSubmit = useCallback(() => {\n setPrivacySettings({\n privacyKey: getPrivacyKey(screen),\n isAllowList: Boolean(isAllowList),\n contactsIds: newSelectedContactIds,\n });\n\n onScreenSelect(SettingsScreens.Privacy);\n }, [isAllowList, newSelectedContactIds, onScreenSelect, screen, setPrivacySettings]);\n\n const lang = useLang();\n\n return (\n <div className=\"NewChat-inner step-1\">\n <Picker\n itemIds={displayedIds || []}\n selectedIds={newSelectedContactIds}\n filterValue={searchQuery}\n filterPlaceholder={isAllowList ? lang('AlwaysShareWithPlaceholder') : lang('NeverShareWithPlaceholder')}\n searchInputId=\"new-group-picker-search\"\n onSelectedIdsChange={handleSelectedContactIdsChange}\n onFilterChange={setSearchQuery}\n />\n\n <FloatingActionButton\n isShown={isSubmitShown}\n onClick={handleSubmit}\n ariaLabel={isAllowList ? lang('AlwaysShareWithTitle') : lang('NeverShareWithTitle')}\n >\n <i className=\"icon-arrow-right\" />\n </FloatingActionButton>\n </div>\n );\n};\n\nfunction getCurrentPrivacySettings(global: GlobalState, screen: SettingsScreens) {\n const { privacy } = global.settings;\n switch (screen) {\n case SettingsScreens.PrivacyPhoneNumberAllowedContacts:\n case SettingsScreens.PrivacyPhoneNumberDeniedContacts:\n return privacy.phoneNumber;\n case SettingsScreens.PrivacyLastSeenAllowedContacts:\n case SettingsScreens.PrivacyLastSeenDeniedContacts:\n return privacy.lastSeen;\n case SettingsScreens.PrivacyProfilePhotoAllowedContacts:\n case SettingsScreens.PrivacyProfilePhotoDeniedContacts:\n return privacy.profilePhoto;\n case SettingsScreens.PrivacyForwardingAllowedContacts:\n case SettingsScreens.PrivacyForwardingDeniedContacts:\n return privacy.forwards;\n case SettingsScreens.PrivacyGroupChatsDeniedContacts:\n case SettingsScreens.PrivacyGroupChatsAllowedContacts:\n return privacy.chatInvite;\n }\n\n return undefined;\n}\n\nexport default memo(withGlobal<OwnProps>(\n (global, { screen }): StateProps => {\n const {\n chats: {\n byId: chatsById,\n listIds,\n orderedPinnedIds,\n },\n currentUserId,\n } = global;\n\n return {\n currentUserId,\n chatsById,\n listIds: listIds.active,\n orderedPinnedIds: orderedPinnedIds.active,\n archivedPinnedIds: orderedPinnedIds.archived,\n archivedListIds: listIds.archived,\n settings: getCurrentPrivacySettings(global, screen),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['setPrivacySettings']),\n)(SettingsPrivacyVisibilityExceptionList));\n","import React, { FC, memo, useCallback } from '../../../lib/teact/teact';\n\nimport { SettingsScreens } from '../../../types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport useFoldersReducer from '../../../hooks/reducers/useFoldersReducer';\nimport useTwoFaReducer from '../../../hooks/reducers/useTwoFaReducer';\n\nimport Transition from '../../ui/Transition';\nimport SettingsHeader from './SettingsHeader';\nimport SettingsMain from './SettingsMain';\nimport SettingsEditProfile from './SettingsEditProfile';\nimport SettingsFolders from './folders/SettingsFolders';\nimport SettingsGeneral from './SettingsGeneral';\nimport SettingsGeneralBackground from './SettingsGeneralBackground';\nimport SettingsGeneralBackgroundColor from './SettingsGeneralBackgroundColor';\nimport SettingsNotifications from './SettingsNotifications';\nimport SettingsPrivacy from './SettingsPrivacy';\nimport SettingsLanguage from './SettingsLanguage';\nimport SettingsPrivacyVisibility from './SettingsPrivacyVisibility';\nimport SettingsPrivacyActiveSessions from './SettingsPrivacyActiveSessions';\nimport SettingsPrivacyBlockedUsers from './SettingsPrivacyBlockedUsers';\nimport SettingsTwoFa from './twoFa/SettingsTwoFa';\nimport SettingsPrivacyVisibilityExceptionList from './SettingsPrivacyVisibilityExceptionList';\n\nimport './Settings.scss';\n\nconst TRANSITION_RENDER_COUNT = Object.keys(SettingsScreens).length / 2;\nconst TRANSITION_DURATION = 200;\n\nexport type OwnProps = {\n currentScreen: SettingsScreens;\n onScreenSelect: (screen: SettingsScreens) => void;\n onReset: () => void;\n};\n\nconst Settings: FC<OwnProps> = ({\n currentScreen,\n onScreenSelect,\n onReset,\n}) => {\n const [foldersState, foldersDispatch] = useFoldersReducer();\n const [twoFaState, twoFaDispatch] = useTwoFaReducer();\n\n const handleReset = useCallback(() => {\n if (\n currentScreen === SettingsScreens.FoldersCreateFolder\n || currentScreen === SettingsScreens.FoldersEditFolder\n ) {\n setTimeout(() => {\n foldersDispatch({ type: 'reset' });\n }, TRANSITION_DURATION);\n }\n\n if (\n currentScreen === SettingsScreens.FoldersIncludedChats\n || currentScreen === SettingsScreens.FoldersExcludedChats\n ) {\n if (foldersState.mode === 'create') {\n onScreenSelect(SettingsScreens.FoldersCreateFolder);\n } else {\n onScreenSelect(SettingsScreens.FoldersEditFolder);\n }\n return;\n }\n\n onReset();\n }, [\n foldersState.mode, foldersDispatch,\n currentScreen, onReset, onScreenSelect,\n ]);\n\n const handleSaveFilter = useCallback(() => {\n foldersDispatch({ type: 'saveFilters' });\n handleReset();\n }, [foldersDispatch, handleReset]);\n\n function renderCurrentSectionContent() {\n switch (currentScreen) {\n case SettingsScreens.Main:\n return (\n <SettingsMain onScreenSelect={onScreenSelect} />\n );\n case SettingsScreens.EditProfile:\n return (\n <SettingsEditProfile />\n );\n case SettingsScreens.General:\n return (\n <SettingsGeneral onScreenSelect={onScreenSelect} />\n );\n case SettingsScreens.Notifications:\n return (\n <SettingsNotifications />\n );\n case SettingsScreens.Privacy:\n return (\n <SettingsPrivacy onScreenSelect={onScreenSelect} />\n );\n case SettingsScreens.Language:\n return (\n <SettingsLanguage />\n );\n case SettingsScreens.GeneralChatBackground:\n return (\n <SettingsGeneralBackground onScreenSelect={onScreenSelect} />\n );\n case SettingsScreens.GeneralChatBackgroundColor:\n return (\n <SettingsGeneralBackgroundColor onScreenSelect={onScreenSelect} />\n );\n case SettingsScreens.PrivacyActiveSessions:\n return (\n <SettingsPrivacyActiveSessions />\n );\n case SettingsScreens.PrivacyBlockedUsers:\n return (\n <SettingsPrivacyBlockedUsers />\n );\n case SettingsScreens.PrivacyPhoneNumber:\n case SettingsScreens.PrivacyLastSeen:\n case SettingsScreens.PrivacyProfilePhoto:\n case SettingsScreens.PrivacyForwarding:\n case SettingsScreens.PrivacyGroupChats:\n return (\n <SettingsPrivacyVisibility screen={currentScreen} onScreenSelect={onScreenSelect} />\n );\n\n case SettingsScreens.PrivacyPhoneNumberAllowedContacts:\n case SettingsScreens.PrivacyLastSeenAllowedContacts:\n case SettingsScreens.PrivacyProfilePhotoAllowedContacts:\n case SettingsScreens.PrivacyForwardingAllowedContacts:\n case SettingsScreens.PrivacyGroupChatsAllowedContacts:\n return (\n <SettingsPrivacyVisibilityExceptionList\n isAllowList\n screen={currentScreen}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case SettingsScreens.PrivacyPhoneNumberDeniedContacts:\n case SettingsScreens.PrivacyLastSeenDeniedContacts:\n case SettingsScreens.PrivacyProfilePhotoDeniedContacts:\n case SettingsScreens.PrivacyForwardingDeniedContacts:\n case SettingsScreens.PrivacyGroupChatsDeniedContacts:\n return (\n <SettingsPrivacyVisibilityExceptionList\n screen={currentScreen}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case SettingsScreens.Folders:\n case SettingsScreens.FoldersCreateFolder:\n case SettingsScreens.FoldersEditFolder:\n case SettingsScreens.FoldersIncludedChats:\n case SettingsScreens.FoldersExcludedChats:\n return (\n <SettingsFolders\n currentScreen={currentScreen}\n state={foldersState}\n dispatch={foldersDispatch}\n onScreenSelect={onScreenSelect}\n onReset={handleReset}\n />\n );\n\n case SettingsScreens.TwoFaDisabled:\n case SettingsScreens.TwoFaNewPassword:\n case SettingsScreens.TwoFaNewPasswordConfirm:\n case SettingsScreens.TwoFaNewPasswordHint:\n case SettingsScreens.TwoFaNewPasswordEmail:\n case SettingsScreens.TwoFaNewPasswordEmailCode:\n case SettingsScreens.TwoFaCongratulations:\n case SettingsScreens.TwoFaEnabled:\n case SettingsScreens.TwoFaChangePasswordCurrent:\n case SettingsScreens.TwoFaChangePasswordNew:\n case SettingsScreens.TwoFaChangePasswordConfirm:\n case SettingsScreens.TwoFaChangePasswordHint:\n case SettingsScreens.TwoFaTurnOff:\n case SettingsScreens.TwoFaRecoveryEmailCurrentPassword:\n case SettingsScreens.TwoFaRecoveryEmail:\n case SettingsScreens.TwoFaRecoveryEmailCode:\n return (\n <SettingsTwoFa\n currentScreen={currentScreen}\n state={twoFaState}\n dispatch={twoFaDispatch}\n onScreenSelect={onScreenSelect}\n />\n );\n\n default:\n return undefined;\n }\n }\n\n function renderCurrentSection() {\n return (\n <>\n <SettingsHeader\n currentScreen={currentScreen}\n onReset={handleReset}\n onSaveFilter={handleSaveFilter}\n editedFolderId={foldersState.folderId}\n />\n {renderCurrentSectionContent()}\n </>\n );\n }\n\n return (\n <Transition\n id=\"Settings\"\n name={IS_MOBILE_SCREEN ? 'slide-layers' : 'push-slide'}\n activeKey={currentScreen}\n renderCount={TRANSITION_RENDER_COUNT}\n >\n {renderCurrentSection}\n </Transition>\n );\n};\n\nexport default memo(Settings);\n","import React, {\n FC, useEffect, useCallback, useMemo, memo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiUser } from '../../../api/types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport { throttle } from '../../../util/schedulers';\nimport searchWords from '../../../util/searchWords';\nimport { pick } from '../../../util/iteratees';\nimport { getUserFullName, getSortedUserIds } from '../../../modules/helpers';\nimport useInfiniteScroll from '../../../hooks/useInfiniteScroll';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport InfiniteScroll from '../../ui/InfiniteScroll';\nimport ListItem from '../../ui/ListItem';\nimport Loading from '../../ui/Loading';\n\nexport type OwnProps = {\n filter: string;\n};\n\ntype StateProps = {\n usersById: Record<number, ApiUser>;\n contactIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadContactList' | 'openChat'>;\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst ContactList: FC<OwnProps & StateProps & DispatchProps> = ({\n filter, usersById, contactIds, loadContactList, openChat,\n}) => {\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadContactList();\n });\n });\n\n const handleClick = useCallback(\n (id: number) => {\n openChat({ id });\n },\n [openChat],\n );\n\n const listIds = useMemo(() => {\n if (!contactIds) {\n return undefined;\n }\n\n const resultIds = filter ? contactIds.filter((id) => {\n const user = usersById[id];\n if (!user) {\n return false;\n }\n const fullName = getUserFullName(user);\n return fullName && searchWords(fullName, filter);\n }) : contactIds;\n\n return getSortedUserIds(resultIds, usersById);\n }, [filter, usersById, contactIds]);\n\n const [viewportIds, getMore] = useInfiniteScroll(undefined, listIds, Boolean(filter));\n\n return (\n <InfiniteScroll items={viewportIds} onLoadMore={getMore} className=\"chat-list custom-scroll\">\n {viewportIds && viewportIds.length ? (\n viewportIds.map((id) => (\n <ListItem\n key={id}\n className=\"chat-item-clickable\"\n onClick={() => handleClick(id)}\n ripple={!IS_MOBILE_SCREEN}\n >\n <PrivateChatInfo userId={id} forceShowSelf avatarSize=\"large\" />\n </ListItem>\n ))\n ) : viewportIds && !viewportIds.length ? (\n <p className=\"no-results\" key=\"no-results\">\n {filter.length ? 'No contacts matched your search.' : 'Contact list is empty.'}\n </p>\n ) : (\n <Loading key=\"loading\" />\n )}\n </InfiniteScroll>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { userIds: contactIds } = global.contactList || {};\n const { byId: usersById } = global.users;\n\n return {\n usersById,\n contactIds,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadContactList', 'openChat']),\n)(ContactList));\n","import React, {\n FC, useCallback, useEffect, useMemo, memo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiUser } from '../../../api/types';\n\nimport { pick, unique } from '../../../util/iteratees';\nimport { throttle } from '../../../util/schedulers';\nimport searchWords from '../../../util/searchWords';\nimport { getSortedUserIds, getUserFullName } from '../../../modules/helpers';\nimport useLang from '../../../hooks/useLang';\n\nimport Picker from '../../common/Picker';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Button from '../../ui/Button';\n\nexport type OwnProps = {\n isChannel?: boolean;\n selectedMemberIds: number[];\n onSelectedMemberIdsChange: (ids: number[]) => void;\n onNextStep: () => void;\n onReset: () => void;\n};\n\ntype StateProps = {\n currentUserId?: number;\n usersById: Record<number, ApiUser>;\n localContactIds?: number[];\n searchQuery?: string;\n isSearching?: boolean;\n localUsers?: ApiUser[];\n globalUsers?: ApiUser[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setGlobalSearchQuery'>;\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst NewChatStep1: FC<OwnProps & StateProps & DispatchProps> = ({\n isChannel,\n selectedMemberIds,\n onSelectedMemberIdsChange,\n onNextStep,\n onReset,\n currentUserId,\n usersById,\n localContactIds,\n searchQuery,\n isSearching,\n localUsers,\n globalUsers,\n loadContactList,\n setGlobalSearchQuery,\n}) => {\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadContactList();\n });\n });\n\n const handleFilterChange = useCallback((query: string) => {\n setGlobalSearchQuery({ query });\n }, [setGlobalSearchQuery]);\n\n const displayedIds = useMemo(() => {\n const contactIds = localContactIds ? localContactIds.filter((id) => id !== currentUserId) : [];\n\n if (!searchQuery) {\n return contactIds;\n }\n\n const foundLocalContacts = contactIds.filter((id) => {\n const user = usersById[id];\n if (!user) {\n return false;\n }\n const fullName = getUserFullName(user);\n return fullName && searchWords(fullName, searchQuery);\n });\n\n return getSortedUserIds(\n unique([\n ...foundLocalContacts,\n ...(localUsers ? localUsers.map((user) => user.id) : []),\n ...(globalUsers ? globalUsers.map((user) => user.id) : []),\n ]) as number[],\n usersById,\n selectedMemberIds,\n );\n }, [localContactIds, searchQuery, localUsers, globalUsers, usersById, selectedMemberIds, currentUserId]);\n\n const handleNextStep = useCallback(() => {\n if (selectedMemberIds.length) {\n setGlobalSearchQuery({ query: '' });\n onNextStep();\n }\n }, [selectedMemberIds, setGlobalSearchQuery, onNextStep]);\n\n const lang = useLang();\n\n return (\n <div className=\"NewChat step-1\">\n <div className=\"left-header\">\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={onReset}\n ariaLabel=\"Return to Chat List\"\n >\n <i className=\"icon-arrow-left\" />\n </Button>\n <h3>{lang('GroupAddMembers')}</h3>\n </div>\n <div className=\"NewChat-inner step-1\">\n <Picker\n itemIds={displayedIds}\n selectedIds={selectedMemberIds}\n filterValue={searchQuery}\n filterPlaceholder={lang('SendMessageTo')}\n searchInputId=\"new-group-picker-search\"\n isLoading={isSearching}\n onSelectedIdsChange={onSelectedMemberIdsChange}\n onFilterChange={handleFilterChange}\n />\n\n <FloatingActionButton\n isShown={Boolean(selectedMemberIds.length)}\n onClick={handleNextStep}\n ariaLabel={isChannel ? 'Continue To Channel Info' : 'Continue To Group Info'}\n >\n <i className=\"icon-arrow-right\" />\n </FloatingActionButton>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { userIds: localContactIds } = global.contactList || {};\n const { byId: usersById } = global.users;\n const { currentUserId } = global;\n\n const {\n query: searchQuery,\n fetchingStatus,\n globalResults,\n localResults,\n } = global.globalSearch;\n const { users: globalUsers } = globalResults || {};\n const { users: localUsers } = localResults || {};\n\n return {\n currentUserId,\n usersById,\n localContactIds,\n searchQuery,\n isSearching: fetchingStatus && fetchingStatus.chats,\n globalUsers,\n localUsers,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadContactList', 'setGlobalSearchQuery']),\n)(NewChatStep1));\n","import React, {\n FC, useState, useCallback, useEffect, memo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ChatCreationProgress } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\n\nimport InputText from '../../ui/InputText';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport AvatarEditable from '../../ui/AvatarEditable';\nimport Button from '../../ui/Button';\nimport ListItem from '../../ui/ListItem';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\n\nexport type OwnProps = {\n isChannel?: boolean;\n memberIds: number[];\n onReset: (forceReturnToChatList?: boolean) => void;\n};\n\ntype StateProps = {\n creationProgress?: ChatCreationProgress;\n creationError?: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'createGroupChat' | 'createChannel'>;\n\n// TODO @implement\nconst MAX_USERS_FOR_LEGACY_CHAT = 199; // Accounting for current user\n\nconst NewChatStep2: FC<OwnProps & StateProps & DispatchProps> = ({\n isChannel,\n memberIds,\n onReset,\n creationProgress,\n creationError,\n createGroupChat,\n createChannel,\n}) => {\n const lang = useLang();\n\n const [title, setTitle] = useState('');\n const [about, setAbout] = useState('');\n const [photo, setPhoto] = useState<File | undefined>();\n const [error, setError] = useState<string | undefined>();\n\n const chatTitleEmptyError = 'Chat title can\\'t be empty';\n const channelTitleEmptyError = 'Channel title can\\'t be empty';\n const chatTooManyUsersError = 'Sorry, creating supergroups is not yet supported';\n\n const isLoading = creationProgress === ChatCreationProgress.InProgress;\n\n const handleTitleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { value } = e.currentTarget;\n const newValue = value.replace(/^\\s+/, '');\n\n setTitle(newValue);\n\n if (newValue !== value) {\n e.currentTarget.value = newValue;\n }\n }, []);\n\n const handleDescriptionChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setAbout(e.currentTarget.value);\n }, []);\n\n const handleCreateGroup = useCallback(() => {\n if (!title.length) {\n setError(chatTitleEmptyError);\n return;\n }\n\n if (memberIds.length > MAX_USERS_FOR_LEGACY_CHAT) {\n setError(chatTooManyUsersError);\n return;\n }\n\n createGroupChat({\n title,\n photo,\n memberIds,\n });\n }, [title, memberIds, createGroupChat, photo, chatTitleEmptyError, chatTooManyUsersError]);\n\n const handleCreateChannel = useCallback(() => {\n if (!title.length) {\n setError(channelTitleEmptyError);\n return;\n }\n\n createChannel({\n title,\n about,\n photo,\n memberIds,\n });\n }, [title, createChannel, about, photo, memberIds, channelTitleEmptyError]);\n\n useEffect(() => {\n if (creationProgress === ChatCreationProgress.Complete) {\n onReset(true);\n }\n }, [creationProgress, onReset]);\n\n const renderedError = creationError || (\n error !== chatTitleEmptyError && error !== channelTitleEmptyError\n ? error\n : undefined\n );\n\n return (\n <div className=\"NewChat\">\n <div className=\"left-header\">\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={() => onReset()}\n ariaLabel=\"Return to member selection\"\n >\n <i className=\"icon-arrow-left\" />\n </Button>\n <h3>{lang(isChannel ? 'NewChannel' : 'NewGroup')}</h3>\n </div>\n <div className=\"NewChat-inner step-2\">\n <AvatarEditable\n onChange={setPhoto}\n title={lang('AddPhoto')}\n />\n <InputText\n value={title}\n onChange={handleTitleChange}\n label={lang(isChannel ? 'EnterChannelName' : 'GroupName')}\n error={error === chatTitleEmptyError || error === channelTitleEmptyError ? error : undefined}\n />\n {isChannel && (\n <>\n <InputText\n value={about}\n onChange={handleDescriptionChange}\n label={lang('DescriptionOptionalPlaceholder')}\n />\n <p className=\"note\">{lang('DescriptionInfo')}</p>\n </>\n )}\n\n {renderedError && (\n <p className=\"error\">{renderedError}</p>\n )}\n\n <h3 className=\"chat-members-heading\">{lang('GroupInfo.ParticipantCount', memberIds.length, 'i')}</h3>\n\n <div className=\"chat-members-list custom-scroll\">\n {memberIds.map((id) => (\n <ListItem inactive className=\"chat-item-clickable\">\n <PrivateChatInfo userId={id} />\n </ListItem>\n ))}\n </div>\n </div>\n\n <FloatingActionButton\n isShown={title.length !== 0}\n onClick={isChannel ? handleCreateChannel : handleCreateGroup}\n disabled={isLoading}\n ariaLabel={isChannel ? lang('ChannelIntro.CreateChannel') : 'Create Group'}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-arrow-right\" />\n )}\n </FloatingActionButton>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n progress: creationProgress,\n error: creationError,\n } = global.chatCreation || {};\n\n return {\n creationProgress,\n creationError,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'createGroupChat', 'createChannel',\n ]),\n)(NewChatStep2));\n","import React, {\n FC, memo, useCallback, useState,\n} from '../../../lib/teact/teact';\n\nimport { LeftColumnContent } from '../../../types';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\n\nimport Transition from '../../ui/Transition';\nimport NewChatStep1 from './NewChatStep1';\nimport NewChatStep2 from './NewChatStep2';\n\nimport './NewChat.scss';\n\nexport type OwnProps = {\n isChannel?: boolean;\n content: LeftColumnContent;\n onContentChange: (content: LeftColumnContent) => void;\n onReset: () => void;\n};\n\nconst RENDER_COUNT = Object.keys(LeftColumnContent).length / 2;\n\nconst NewChat: FC<OwnProps> = ({\n isChannel = false,\n content,\n onContentChange,\n onReset,\n}) => {\n const [newChatMemberIds, setNewChatMemberIds] = useState<number[]>([]);\n\n const handleNextStep = useCallback(() => {\n onContentChange(isChannel ? LeftColumnContent.NewChannelStep2 : LeftColumnContent.NewGroupStep2);\n }, [isChannel, onContentChange]);\n\n return (\n <Transition\n id=\"NewChat\"\n name={IS_MOBILE_SCREEN ? 'slide-layers' : 'push-slide'}\n renderCount={RENDER_COUNT}\n activeKey={content}\n >\n {() => {\n switch (content) {\n case LeftColumnContent.NewChannelStep1:\n case LeftColumnContent.NewGroupStep1:\n return (\n <NewChatStep1\n isChannel={isChannel}\n selectedMemberIds={newChatMemberIds}\n onSelectedMemberIdsChange={setNewChatMemberIds}\n onNextStep={handleNextStep}\n onReset={onReset}\n />\n );\n case LeftColumnContent.NewChannelStep2:\n case LeftColumnContent.NewGroupStep2:\n return (\n <NewChatStep2\n isChannel={isChannel}\n memberIds={newChatMemberIds}\n onReset={onReset}\n />\n );\n default:\n return undefined;\n }\n }}\n </Transition>\n );\n};\n\nexport default memo(NewChat);\n","import React, { FC, memo } from '../../lib/teact/teact';\n\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\nimport ChatList from './main/ChatList';\n\nimport './ArchivedChats.scss';\n\nexport type OwnProps = {\n onReset: () => void;\n};\n\nconst ArchivedChats: FC<OwnProps> = ({ onReset }) => {\n const lang = useLang();\n\n return (\n <div className=\"ArchivedChats\">\n <div className=\"left-header\">\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={onReset}\n ariaLabel=\"Return to chat list\"\n >\n <i className=\"icon-arrow-left\" />\n </Button>\n <h3>{lang('ArchivedChats')}</h3>\n </div>\n <ChatList folderType=\"archived\" noChatsText=\"Archive is empty.\" />\n </div>\n );\n};\n\nexport default memo(ArchivedChats);\n","const IGNORED_KEYS: Record<string, boolean> = {\n Down: true,\n ArrowDown: true,\n Up: true,\n ArrowUp: true,\n Left: true,\n ArrowLeft: true,\n Right: true,\n ArrowRight: true,\n ' ': true,\n PageUp: true,\n PageDown: true,\n End: true,\n Home: true,\n Tab: true,\n};\n\nconst preventDefault = (e: Event) => {\n e.preventDefault();\n};\n\nfunction preventDefaultForScrollKeys(e: KeyboardEvent) {\n if (IGNORED_KEYS[e.key]) {\n preventDefault(e);\n }\n}\n\nexport function disableScrolling() {\n // Disable scrolling in Chrome\n document.addEventListener('wheel', preventDefault, { passive: false });\n window.ontouchmove = preventDefault; // mobile\n document.onkeydown = preventDefaultForScrollKeys;\n}\n\nexport function enableScrolling() {\n document.removeEventListener('wheel', preventDefault); // Enable scrolling in Chrome\n // eslint-disable-next-line no-null/no-null\n window.ontouchmove = null;\n // eslint-disable-next-line no-null/no-null\n document.onkeydown = null;\n}\n","import { ApiMediaFormat, ApiMessage } from '../../../../api/types';\n\nimport * as mediaLoader from '../../../../util/mediaLoader';\nimport { getMessageMediaHash, getMessagePhoto, getMessageText } from '../../../../modules/helpers';\nimport { CLIPBOARD_ITEM_SUPPORTED, copyImageToClipboard, copyTextToClipboard } from '../../../../util/clipboard';\n\ntype ICopyOptions = {\n label: string;\n handler: () => void;\n}[];\n\nexport function getMessageCopyOptions(\n message: ApiMessage, afterEffect?: () => void, onCopyLink?: () => void,\n): ICopyOptions {\n const options: ICopyOptions = [];\n const text = getMessageText(message);\n const photo = getMessagePhoto(message);\n const mediaHash = getMessageMediaHash(message, 'inline')!;\n const canImageBeCopied = photo && mediaHash && CLIPBOARD_ITEM_SUPPORTED;\n const selection = window.getSelection();\n\n if (canImageBeCopied) {\n options.push({\n label: 'Copy Media',\n handler: () => {\n mediaLoader.fetch(mediaHash, ApiMediaFormat.BlobUrl).then(copyImageToClipboard);\n\n if (afterEffect) {\n afterEffect();\n }\n },\n });\n }\n\n if (text) {\n // Detect if the user has selection in the current message\n const hasSelection = Boolean((\n selection\n && selection.anchorNode\n && selection.anchorNode.parentNode\n && (selection.anchorNode.parentNode as HTMLElement).closest('.Message .content-inner')\n && selection.toString().replace(/(?:\\r\\n|\\r|\\n)/g, '') !== ''\n ));\n\n options.push({\n label: getCopyLabel(hasSelection, canImageBeCopied),\n handler: () => {\n const clipboardText = hasSelection && selection ? selection.toString() : text;\n copyTextToClipboard(clipboardText);\n\n if (afterEffect) {\n afterEffect();\n }\n },\n });\n }\n\n if (onCopyLink) {\n options.push({\n label: 'CopyMessageLink',\n handler: () => {\n onCopyLink();\n\n if (afterEffect) {\n afterEffect();\n }\n },\n });\n }\n\n return options;\n}\n\nfunction getCopyLabel(hasSelection: boolean, canImageBeCopied: boolean): string {\n if (hasSelection) {\n return 'Copy Selected Text';\n }\n\n if (canImageBeCopied) {\n return 'Copy Text';\n }\n\n return 'Copy';\n}\n","import React, { FC, useCallback, useEffect } from '../../../lib/teact/teact';\n\nimport { ApiMessage } from '../../../api/types';\nimport { IAnchorPosition } from '../../../types';\n\nimport { getMessageCopyOptions } from './helpers/copyOptions';\nimport useContextMenuPosition from '../../../hooks/useContextMenuPosition';\nimport { dispatchHeavyAnimationEvent } from '../../../hooks/useHeavyAnimationCheck';\nimport useLang from '../../../hooks/useLang';\n\nimport Menu from '../../ui/Menu';\nimport MenuItem from '../../ui/MenuItem';\n\nimport './MessageContextMenu.scss';\n\ntype OwnProps = {\n isOpen: boolean;\n anchor: IAnchorPosition;\n message: ApiMessage;\n canSendNow?: boolean;\n canReschedule?: boolean;\n canReply?: boolean;\n canPin?: boolean;\n canUnpin?: boolean;\n canDelete?: boolean;\n canEdit?: boolean;\n canForward?: boolean;\n canFaveSticker?: boolean;\n canUnfaveSticker?: boolean;\n canCopy?: boolean;\n canCopyLink?: boolean;\n canSelect?: boolean;\n onReply: () => void;\n onEdit: () => void;\n onPin: () => void;\n onUnpin: () => void;\n onForward: () => void;\n onDelete: () => void;\n onFaveSticker: () => void;\n onUnfaveSticker: () => void;\n onSelect: () => void;\n onSend: () => void;\n onReschedule: () => void;\n onClose: () => void;\n onCloseAnimationEnd?: () => void;\n onCopyLink?: () => void;\n};\n\nconst ANIMATION_DURATION = 200;\nconst SCROLLBAR_WIDTH = 10;\n\nconst MessageContextMenu: FC<OwnProps> = ({\n isOpen,\n message,\n anchor,\n canSendNow,\n canReschedule,\n canReply,\n canEdit,\n canPin,\n canUnpin,\n canDelete,\n canForward,\n canFaveSticker,\n canUnfaveSticker,\n canCopy,\n canCopyLink,\n canSelect,\n onReply,\n onEdit,\n onPin,\n onUnpin,\n onForward,\n onDelete,\n onFaveSticker,\n onUnfaveSticker,\n onSelect,\n onSend,\n onReschedule,\n onClose,\n onCloseAnimationEnd,\n onCopyLink,\n}) => {\n useEffect(() => {\n dispatchHeavyAnimationEvent(ANIMATION_DURATION);\n }, [isOpen]);\n\n const copyOptions = getMessageCopyOptions(message, onClose, canCopyLink ? onCopyLink : undefined);\n\n const getTriggerElement = useCallback(() => {\n return document.querySelector(`.active > .MessageList div[data-message-id=\"${message.id}\"]`);\n }, [message.id]);\n\n const getRootElement = useCallback(\n () => document.querySelector('.active > .MessageList'),\n [],\n );\n\n const getMenuElement = useCallback(\n () => document.querySelector('.MessageContextMenu .bubble'),\n [],\n );\n\n const { positionX, positionY, style } = useContextMenuPosition(\n anchor,\n getTriggerElement,\n getRootElement,\n getMenuElement,\n SCROLLBAR_WIDTH,\n (document.querySelector('.MiddleHeader') as HTMLElement).offsetHeight,\n );\n\n const lang = useLang();\n\n return (\n <Menu\n isOpen={isOpen}\n positionX={positionX}\n positionY={positionY}\n style={style}\n className=\"MessageContextMenu fluid\"\n onClose={onClose}\n onCloseAnimationEnd={onCloseAnimationEnd}\n >\n {canSendNow && <MenuItem icon=\"send-outline\" onClick={onSend}>{lang('MessageScheduleSend')}</MenuItem>}\n {canReschedule && <MenuItem icon=\"schedule\" onClick={onReschedule}>{lang('MessageScheduleEditTime')}</MenuItem>}\n {canReply && <MenuItem icon=\"reply\" onClick={onReply}>{lang('Reply')}</MenuItem>}\n {canEdit && <MenuItem icon=\"edit\" onClick={onEdit}>{lang('Edit')}</MenuItem>}\n {canFaveSticker && <MenuItem icon=\"favorite\" onClick={onFaveSticker}>{lang('AddToFavorites')}</MenuItem>}\n {canUnfaveSticker && (\n <MenuItem icon=\"favorite\" onClick={onUnfaveSticker}>{lang('Stickers.RemoveFromFavorites')}</MenuItem>\n )}\n {canCopy && copyOptions.map((options) => (\n <MenuItem key={options.label} icon=\"copy\" onClick={options.handler}>{lang(options.label)}</MenuItem>\n ))}\n {canPin && <MenuItem icon=\"pin\" onClick={onPin}>{lang('DialogPin')}</MenuItem>}\n {canUnpin && <MenuItem icon=\"unpin\" onClick={onUnpin}>{lang('DialogUnpin')}</MenuItem>}\n {canForward && <MenuItem icon=\"forward\" onClick={onForward}>{lang('Forward')}</MenuItem>}\n {canSelect && <MenuItem icon=\"select\" onClick={onSelect}>{lang('Common.Select')}</MenuItem>}\n {canDelete && <MenuItem destructive icon=\"delete\" onClick={onDelete}>{lang('Delete')}</MenuItem>}\n </Menu>\n );\n};\n\nexport default MessageContextMenu;\n","import React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions, MessageListType } from '../../../global/types';\nimport { ApiMessage } from '../../../api/types';\nimport { IAlbum, IAnchorPosition } from '../../../types';\nimport { selectAllowedMessageActions, selectCurrentMessageList } from '../../../modules/selectors';\nimport { disableScrolling, enableScrolling } from '../../../util/scrollLock';\nimport { pick } from '../../../util/iteratees';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport useFlag from '../../../hooks/useFlag';\n\nimport DeleteMessageModal from '../../common/DeleteMessageModal';\nimport PinMessageModal from '../../common/PinMessageModal';\nimport MessageContextMenu from './MessageContextMenu';\nimport CalendarModal from '../../common/CalendarModal';\nimport { getDayStartAt } from '../../../util/dateFormat';\n\nexport type OwnProps = {\n isOpen: boolean;\n message: ApiMessage;\n album?: IAlbum;\n anchor: IAnchorPosition;\n messageListType: MessageListType;\n onClose: () => void;\n onCloseAnimationEnd: () => void;\n};\n\ntype StateProps = {\n noOptions?: boolean;\n canSendNow?: boolean;\n canReschedule?: boolean;\n canReply?: boolean;\n canPin?: boolean;\n canUnpin?: boolean;\n canDelete?: boolean;\n canEdit?: boolean;\n canForward?: boolean;\n canFaveSticker?: boolean;\n canUnfaveSticker?: boolean;\n canCopy?: boolean;\n canCopyLink?: boolean;\n canSelect?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'setReplyingToId' | 'setEditingId' | 'pinMessage' | 'openForwardMenu' |\n 'faveSticker' | 'unfaveSticker' | 'toggleMessageSelection' | 'sendScheduledMessages' | 'rescheduleMessage' |\n 'loadMessageLink'\n)>;\n\nconst ContextMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n messageListType,\n message,\n album,\n anchor,\n onClose,\n onCloseAnimationEnd,\n noOptions,\n canSendNow,\n canReschedule,\n canReply,\n canPin,\n canUnpin,\n canDelete,\n canEdit,\n canForward,\n canFaveSticker,\n canUnfaveSticker,\n canCopy,\n canCopyLink,\n canSelect,\n setReplyingToId,\n setEditingId,\n pinMessage,\n openForwardMenu,\n faveSticker,\n unfaveSticker,\n toggleMessageSelection,\n sendScheduledMessages,\n rescheduleMessage,\n loadMessageLink,\n}) => {\n const { transitionClassNames } = useShowTransition(isOpen, onCloseAnimationEnd, undefined, false);\n const [isMenuOpen, setIsMenuOpen] = useState(true);\n const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);\n const [isPinModalOpen, setIsPinModalOpen] = useState(false);\n const [isCalendarOpen, openCalendar, closeCalendar] = useFlag();\n\n const handleDelete = useCallback(() => {\n setIsMenuOpen(false);\n setIsDeleteModalOpen(true);\n }, []);\n\n const closeMenu = useCallback(() => {\n setIsMenuOpen(false);\n onClose();\n }, [onClose]);\n\n const closeDeleteModal = useCallback(() => {\n setIsDeleteModalOpen(false);\n onClose();\n }, [onClose]);\n\n const closePinModal = useCallback(() => {\n setIsPinModalOpen(false);\n onClose();\n }, [onClose]);\n\n const handleCloseCalendar = useCallback(() => {\n closeCalendar();\n onClose();\n }, [closeCalendar, onClose]);\n\n const handleReply = useCallback(() => {\n setReplyingToId({ messageId: message.id });\n closeMenu();\n }, [setReplyingToId, message.id, closeMenu]);\n\n const handleEdit = useCallback(() => {\n setEditingId({ messageId: message.id });\n closeMenu();\n }, [setEditingId, message.id, closeMenu]);\n\n const handlePin = useCallback(() => {\n setIsMenuOpen(false);\n setIsPinModalOpen(true);\n }, []);\n\n const handleUnpin = useCallback(() => {\n pinMessage({ messageId: message.id, isUnpin: true });\n closeMenu();\n }, [pinMessage, message.id, closeMenu]);\n\n const handleForward = useCallback(() => {\n closeMenu();\n if (album && album.messages) {\n const messageIds = album.messages.map(({ id }) => id);\n openForwardMenu({ fromChatId: message.chatId, messageIds });\n } else {\n openForwardMenu({ fromChatId: message.chatId, messageIds: [message.id] });\n }\n }, [openForwardMenu, message, closeMenu, album]);\n\n const handleFaveSticker = useCallback(() => {\n closeMenu();\n faveSticker({ sticker: message.content.sticker });\n }, [closeMenu, message.content.sticker, faveSticker]);\n\n const handleUnfaveSticker = useCallback(() => {\n closeMenu();\n unfaveSticker({ sticker: message.content.sticker });\n }, [closeMenu, message.content.sticker, unfaveSticker]);\n\n const handleSelectMessage = useCallback(() => {\n const params = album && album.messages\n ? {\n messageId: message.id,\n childMessageIds: album.messages.map(({ id }) => id),\n withShift: false,\n }\n : { messageId: message.id, withShift: false };\n\n toggleMessageSelection(params);\n closeMenu();\n }, [closeMenu, message.id, toggleMessageSelection, album]);\n\n const handleScheduledMessageSend = useCallback(() => {\n sendScheduledMessages({ chatId: message.chatId, id: message.id });\n closeMenu();\n }, [closeMenu, message.chatId, message.id, sendScheduledMessages]);\n\n const handleOpenCalendar = useCallback(() => {\n setIsMenuOpen(false);\n openCalendar();\n }, [openCalendar]);\n\n const handleRescheduleMessage = useCallback((date: Date) => {\n rescheduleMessage({\n chatId: message.chatId,\n messageId: message.id,\n scheduledAt: Math.round(date.getTime() / 1000),\n });\n }, [message.chatId, message.id, rescheduleMessage]);\n\n const handleCopyLink = useCallback(() => {\n loadMessageLink({\n messageId: message.id,\n chatId: message.chatId,\n });\n closeMenu();\n }, [closeMenu, loadMessageLink, message.chatId, message.id]);\n\n useEffect(() => {\n disableScrolling();\n\n return enableScrolling;\n }, []);\n\n if (noOptions) {\n closeMenu();\n\n return undefined;\n }\n\n const scheduledMaxDate = new Date();\n scheduledMaxDate.setFullYear(scheduledMaxDate.getFullYear() + 1);\n\n return (\n <div className={['ContextMenuContainer', transitionClassNames].join(' ')}>\n <MessageContextMenu\n message={message}\n isOpen={isMenuOpen}\n anchor={anchor}\n canSendNow={canSendNow}\n canReschedule={canReschedule}\n canReply={canReply}\n canDelete={canDelete}\n canPin={canPin}\n canUnpin={canUnpin}\n canEdit={canEdit}\n canForward={canForward}\n canFaveSticker={canFaveSticker}\n canUnfaveSticker={canUnfaveSticker}\n canCopy={canCopy}\n canCopyLink={canCopyLink}\n canSelect={canSelect}\n onReply={handleReply}\n onEdit={handleEdit}\n onPin={handlePin}\n onUnpin={handleUnpin}\n onForward={handleForward}\n onDelete={handleDelete}\n onFaveSticker={handleFaveSticker}\n onUnfaveSticker={handleUnfaveSticker}\n onSelect={handleSelectMessage}\n onSend={handleScheduledMessageSend}\n onReschedule={handleOpenCalendar}\n onClose={closeMenu}\n onCopyLink={handleCopyLink}\n />\n <DeleteMessageModal\n isOpen={isDeleteModalOpen}\n isSchedule={messageListType === 'scheduled'}\n onClose={closeDeleteModal}\n album={album}\n message={message}\n />\n <PinMessageModal\n isOpen={isPinModalOpen}\n messageId={message.id}\n chatId={message.chatId}\n onClose={closePinModal}\n />\n <CalendarModal\n isOpen={isCalendarOpen}\n withTimePicker\n selectedAt={message.date * 1000}\n maxAt={getDayStartAt(scheduledMaxDate)}\n isFutureMode\n onClose={handleCloseCalendar}\n onSubmit={handleRescheduleMessage}\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { message, messageListType }): StateProps => {\n const { threadId } = selectCurrentMessageList(global) || {};\n const {\n noOptions,\n canReply,\n canPin,\n canUnpin,\n canDelete,\n canEdit,\n canForward,\n canFaveSticker,\n canUnfaveSticker,\n canCopy,\n canCopyLink,\n canSelect,\n } = (threadId && selectAllowedMessageActions(global, message, threadId)) || {};\n const isPinned = messageListType === 'pinned';\n const isScheduled = messageListType === 'scheduled';\n\n return {\n noOptions,\n canSendNow: isScheduled,\n canReschedule: isScheduled,\n canReply: !isPinned && !isScheduled && canReply,\n canPin: !isScheduled && canPin,\n canUnpin: !isScheduled && canUnpin,\n canDelete,\n canEdit: !isPinned && canEdit,\n canForward: !isScheduled && canForward,\n canFaveSticker: !isScheduled && canFaveSticker,\n canUnfaveSticker: !isScheduled && canUnfaveSticker,\n canCopy,\n canCopyLink: !isScheduled && canCopyLink,\n canSelect,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'setReplyingToId',\n 'setEditingId',\n 'pinMessage',\n 'openForwardMenu',\n 'faveSticker',\n 'unfaveSticker',\n 'toggleMessageSelection',\n 'sendScheduledMessages',\n 'rescheduleMessage',\n 'loadMessageLink',\n ]),\n)(ContextMenuContainer));\n","import React, {\n FC, memo, useCallback, useEffect, useRef,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiSticker, ApiStickerSet } from '../../api/types';\nimport { GlobalActions } from '../../global/types';\n\nimport { STICKER_SIZE_MODAL } from '../../config';\nimport { pick } from '../../util/iteratees';\nimport { selectStickerSet } from '../../modules/selectors';\nimport { useIntersectionObserver } from '../../hooks/useIntersectionObserver';\n\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\nimport Loading from '../ui/Loading';\nimport StickerButton from './StickerButton';\n\nimport './StickerSetModal.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n fromSticker: ApiSticker;\n onClose: () => void;\n};\n\ntype StateProps = {\n stickerSet?: ApiStickerSet;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadStickers' | 'toggleStickerSet' | 'sendMessage'>;\n\nconst INTERSECTION_THROTTLE = 200;\n\nconst StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n fromSticker,\n stickerSet,\n onClose,\n loadStickers,\n toggleStickerSet,\n sendMessage,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n\n const {\n observe: observeIntersection,\n } = useIntersectionObserver({ rootRef: containerRef, throttleMs: INTERSECTION_THROTTLE, isDisabled: !isOpen });\n\n useEffect(() => {\n if (isOpen) {\n const { stickerSetId, stickerSetAccessHash } = fromSticker;\n loadStickers({ stickerSetId, stickerSetAccessHash });\n }\n }, [isOpen, fromSticker, loadStickers]);\n\n const handleSelect = useCallback((sticker: ApiSticker) => {\n sticker = {\n ...sticker,\n isPreloadedGlobally: true,\n };\n\n sendMessage({ sticker });\n onClose();\n }, [onClose, sendMessage]);\n\n const handleButtonClick = useCallback(() => {\n toggleStickerSet({ stickerSetId: fromSticker.stickerSetId });\n onClose();\n }, [fromSticker.stickerSetId, onClose, toggleStickerSet]);\n\n return (\n <Modal\n className=\"StickerSetModal\"\n isOpen={isOpen}\n onClose={onClose}\n hasCloseButton\n title={stickerSet ? stickerSet.title : 'Sticker Set'}\n >\n {stickerSet && stickerSet.stickers ? (\n <>\n <div ref={containerRef} className=\"stickers custom-scroll\">\n {stickerSet.stickers.map((sticker) => (\n <StickerButton\n sticker={sticker}\n size={STICKER_SIZE_MODAL}\n observeIntersection={observeIntersection}\n onClick={handleSelect}\n clickArg={sticker}\n />\n ))}\n </div>\n <div className=\"button-wrapper\">\n <Button\n size=\"smaller\"\n fluid\n color={stickerSet.installedDate ? 'danger' : 'primary'}\n onClick={handleButtonClick}\n >\n {`${stickerSet.installedDate ? 'Remove' : 'Add'} ${stickerSet.count} stickers`}\n </Button>\n </div>\n </>\n ) : (\n <Loading />\n )}\n </Modal>\n );\n};\n\nexport default memo(withGlobal(\n (global, { fromSticker }: OwnProps) => {\n return { stickerSet: selectStickerSet(global, fromSticker.stickerSetId) };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadStickers',\n 'toggleStickerSet',\n 'sendMessage',\n ]),\n)(StickerSetModal));\n","import React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiChat } from '../../api/types';\nimport { IAnchorPosition } from '../../types';\n\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport { disableScrolling, enableScrolling } from '../../util/scrollLock';\nimport { selectChat } from '../../modules/selectors';\nimport { pick } from '../../util/iteratees';\nimport { isChatPrivate, getCanDeleteChat } from '../../modules/helpers';\nimport useShowTransition from '../../hooks/useShowTransition';\nimport useLang from '../../hooks/useLang';\n\nimport Portal from '../ui/Portal';\nimport Menu from '../ui/Menu';\nimport MenuItem from '../ui/MenuItem';\nimport DeleteChatModal from '../common/DeleteChatModal';\n\nimport './HeaderMenuContainer.scss';\n\ntype DispatchProps = Pick<GlobalActions, 'updateChatMutedState' | 'enterMessageSelectMode'>;\n\nexport type OwnProps = {\n chatId: number;\n threadId: number;\n isOpen: boolean;\n anchor: IAnchorPosition;\n isChannel?: boolean;\n canSubscribe?: boolean;\n canSearch?: boolean;\n canMute?: boolean;\n canSelect?: boolean;\n canLeave?: boolean;\n onSubscribeChannel: () => void;\n onSearchClick: () => void;\n onClose: () => void;\n onCloseAnimationEnd: () => void;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n isPrivate?: boolean;\n isMuted?: boolean;\n canDeleteChat?: boolean;\n};\n\nconst HeaderMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({\n chatId,\n isOpen,\n anchor,\n isChannel,\n canSubscribe,\n canSearch,\n canMute,\n canSelect,\n canLeave,\n chat,\n isPrivate,\n isMuted,\n canDeleteChat,\n onSubscribeChannel,\n onSearchClick,\n onClose,\n onCloseAnimationEnd,\n updateChatMutedState,\n enterMessageSelectMode,\n}) => {\n const [isMenuOpen, setIsMenuOpen] = useState(true);\n const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);\n const { x, y } = anchor;\n\n useShowTransition(isOpen, onCloseAnimationEnd, undefined, false);\n\n const handleDelete = useCallback(() => {\n setIsMenuOpen(false);\n setIsDeleteModalOpen(true);\n }, []);\n\n const closeMenu = useCallback(() => {\n setIsMenuOpen(false);\n onClose();\n }, [onClose]);\n\n const closeDeleteModal = useCallback(() => {\n setIsDeleteModalOpen(false);\n onClose();\n }, [onClose]);\n\n const handleToggleMuteClick = useCallback(() => {\n updateChatMutedState({ chatId, isMuted: !isMuted });\n closeMenu();\n }, [chatId, closeMenu, isMuted, updateChatMutedState]);\n\n const handleSubscribe = useCallback(() => {\n onSubscribeChannel();\n closeMenu();\n }, [closeMenu, onSubscribeChannel]);\n\n const handleSearch = useCallback(() => {\n onSearchClick();\n closeMenu();\n }, [closeMenu, onSearchClick]);\n\n const handleSelectMessages = useCallback(() => {\n enterMessageSelectMode();\n closeMenu();\n }, [closeMenu, enterMessageSelectMode]);\n\n useEffect(() => {\n disableScrolling();\n\n return enableScrolling;\n }, []);\n\n const lang = useLang();\n\n return (\n <Portal>\n <div className=\"HeaderMenuContainer\">\n <Menu\n isOpen={isMenuOpen}\n positionX=\"right\"\n style={`left: ${x}px;top: ${y}px;`}\n onClose={closeMenu}\n >\n {IS_MOBILE_SCREEN && canSubscribe && (\n <MenuItem\n icon={isChannel ? 'channel' : 'group'}\n onClick={handleSubscribe}\n >\n {lang(isChannel ? 'Subscribe' : 'Join Group')}\n </MenuItem>\n )}\n {IS_MOBILE_SCREEN && canSearch && (\n <MenuItem\n icon=\"search\"\n onClick={handleSearch}\n >\n {lang('Search')}\n </MenuItem>\n )}\n {canMute && (\n <MenuItem\n icon={isMuted ? 'unmute' : 'mute'}\n onClick={handleToggleMuteClick}\n >\n {lang(isMuted ? 'ChatsUnmute' : 'ChatsMute')}\n </MenuItem>\n )}\n {canSelect && (\n <MenuItem\n icon=\"select\"\n onClick={handleSelectMessages}\n >\n {lang('ReportSelectMessages')}\n </MenuItem>\n )}\n {canLeave && (\n <MenuItem\n destructive\n icon=\"delete\"\n onClick={handleDelete}\n >\n {lang(isPrivate ? 'Delete' : (canDeleteChat ? 'Delete and Leave' : 'Leave'))}\n </MenuItem>\n )}\n </Menu>\n {chat && (\n <DeleteChatModal\n isOpen={isDeleteModalOpen}\n onClose={closeDeleteModal}\n chat={chat}\n />\n )}\n </div>\n </Portal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n if (!chat || chat.isRestricted) {\n return {};\n }\n\n return {\n chat,\n isMuted: chat.isMuted,\n isPrivate: isChatPrivate(chat.id),\n canDeleteChat: getCanDeleteChat(chat),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'updateChatMutedState',\n 'enterMessageSelectMode',\n ]),\n)(HeaderMenuContainer));\n","import React, {\n FC, memo, useCallback, useEffect, useRef, useState, useLayoutEffect,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiChat } from '../../api/types';\nimport { GlobalActions } from '../../global/types';\n\nimport { debounce } from '../../util/schedulers';\nimport { selectCurrentTextSearch, selectCurrentChat } from '../../modules/selectors';\nimport { pick } from '../../util/iteratees';\nimport useFlag from '../../hooks/useFlag';\nimport useLang from '../../hooks/useLang';\n\nimport Button from '../ui/Button';\nimport SearchInput from '../ui/SearchInput';\nimport CalendarModal from '../common/CalendarModal';\n\nimport './MobileSearch.scss';\n\nexport type OwnProps = {\n isActive: boolean;\n};\n\ntype StateProps = {\n isActive?: boolean;\n chat?: ApiChat;\n query?: string;\n totalCount?: number;\n foundIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'setLocalTextSearchQuery' | 'searchTextMessagesLocal' | 'closeLocalTextSearch' | 'searchMessagesByDate' |\n 'focusMessage'\n)>;\n\nconst runDebouncedForSearch = debounce((cb) => cb(), 200, false);\n\nconst MobileSearchFooter: FC<StateProps & DispatchProps> = ({\n isActive,\n chat,\n query,\n totalCount,\n foundIds,\n setLocalTextSearchQuery,\n searchTextMessagesLocal,\n focusMessage,\n closeLocalTextSearch,\n searchMessagesByDate,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n const [focusedIndex, setFocusedIndex] = useState(0);\n const [isCalendarOpen, openCalendar, closeCalendar] = useFlag();\n\n // Fix for iOS keyboard\n useEffect(() => {\n const { visualViewport } = window as any;\n if (!visualViewport) {\n return undefined;\n }\n\n const mainEl = document.getElementById('Main') as HTMLDivElement;\n const handleResize = () => {\n const { activeElement } = document;\n if (activeElement && (activeElement === inputRef.current)) {\n const { pageTop, height } = visualViewport;\n mainEl.style.transform = `translateY(${pageTop}px)`;\n mainEl.style.height = `${height}px`;\n document.documentElement.scrollTop = pageTop;\n } else {\n mainEl.style.transform = '';\n mainEl.style.height = '';\n }\n };\n\n visualViewport.addEventListener('resize', handleResize);\n\n return () => {\n visualViewport.removeEventListener('resize', handleResize);\n };\n }, []);\n\n // Focus message\n useEffect(() => {\n if (chat && foundIds && foundIds.length) {\n focusMessage({ chatId: chat.id, messageId: foundIds[foundIds.length - 1] });\n setFocusedIndex(0);\n } else {\n setFocusedIndex(-1);\n }\n }, [chat, focusMessage, foundIds]);\n\n // Disable native up/down buttons on iOS\n useEffect(() => {\n Array.from(document.querySelectorAll<HTMLInputElement>('input')).forEach((input) => {\n input.disabled = Boolean(isActive && input !== inputRef.current);\n });\n\n Array.from(document.querySelectorAll<HTMLDivElement>('div[contenteditable]')).forEach((div) => {\n div.contentEditable = isActive ? 'false' : 'true';\n });\n }, [isActive]);\n\n // Blur on exit\n useEffect(() => {\n if (!isActive) {\n inputRef.current!.blur();\n }\n }, [isActive]);\n\n useLayoutEffect(() => {\n const searchInput = document.querySelector<HTMLInputElement>('#MobileSearch input')!;\n searchInput.blur();\n }, [isCalendarOpen]);\n\n const handleMessageSearchQueryChange = useCallback((newQuery: string) => {\n setLocalTextSearchQuery({ query: newQuery });\n\n if (newQuery.length) {\n runDebouncedForSearch(searchTextMessagesLocal);\n }\n }, [searchTextMessagesLocal, setLocalTextSearchQuery]);\n\n const handleJumpToDate = useCallback((date: Date) => {\n searchMessagesByDate({ timestamp: date.valueOf() / 1000 });\n closeCalendar();\n }, [closeCalendar, searchMessagesByDate]);\n\n const handleUp = useCallback(() => {\n if (chat && foundIds) {\n const newFocusIndex = focusedIndex + 1;\n focusMessage({ chatId: chat.id, messageId: foundIds[foundIds.length - 1 - newFocusIndex] });\n setFocusedIndex(newFocusIndex);\n }\n }, [chat, focusedIndex, focusMessage, foundIds]);\n\n const handleDown = useCallback(() => {\n if (chat && foundIds) {\n const newFocusIndex = focusedIndex - 1;\n focusMessage({ chatId: chat.id, messageId: foundIds[foundIds.length - 1 - newFocusIndex] });\n setFocusedIndex(newFocusIndex);\n }\n }, [chat, focusedIndex, focusMessage, foundIds]);\n\n const lang = useLang();\n\n return (\n <div id=\"MobileSearch\" className={isActive ? 'active' : ''}>\n <div className=\"header\">\n <Button\n size=\"smaller\"\n round\n color=\"translucent\"\n onClick={closeLocalTextSearch}\n >\n <i className=\"icon-arrow-left\" />\n </Button>\n <SearchInput\n ref={inputRef}\n value={query}\n onChange={handleMessageSearchQueryChange}\n />\n </div>\n <div className=\"footer\">\n <div className=\"counter\">\n {query ? (\n foundIds && foundIds.length ? (\n `${focusedIndex + 1} of ${totalCount}`\n ) : foundIds && !foundIds.length ? (\n 'No results'\n ) : (\n ''\n )\n ) : (\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={openCalendar}\n ariaLabel=\"Search messages by date\"\n >\n <i className=\"icon-calendar\" />\n </Button>\n )}\n </div>\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={handleUp}\n disabled={!foundIds || !foundIds.length || focusedIndex === foundIds.length - 1}\n >\n <i className=\"icon-up\" />\n </Button>\n <Button\n round\n size=\"smaller\"\n color=\"translucent\"\n onClick={handleDown}\n disabled={!foundIds || !foundIds.length || focusedIndex === 0}\n >\n <i className=\"icon-down\" />\n </Button>\n </div>\n <CalendarModal\n isOpen={isCalendarOpen}\n isPastMode\n submitButtonLabel={lang('JumpToDate')}\n onClose={closeCalendar}\n onSubmit={handleJumpToDate}\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const chat = selectCurrentChat(global);\n if (!chat) {\n return {};\n }\n\n const { query, results } = selectCurrentTextSearch(global) || {};\n const { totalCount, foundIds } = results || {};\n\n return {\n chat,\n query,\n totalCount,\n foundIds,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'setLocalTextSearchQuery',\n 'searchTextMessagesLocal',\n 'focusMessage',\n 'closeLocalTextSearch',\n 'searchMessagesByDate',\n ]),\n)(MobileSearchFooter));\n","function isFullyVisible(container: HTMLElement, element: HTMLElement) {\n const viewportY1 = container.scrollTop;\n const viewportY2 = viewportY1 + container.offsetHeight;\n const y1 = element.offsetTop;\n const y2 = y1 + element.offsetHeight;\n return y1 > viewportY1 && y2 < viewportY2;\n}\n\nexport default isFullyVisible;\n","import React, {\n FC, useCallback, useEffect, useState, useRef, memo,\n} from '../../../lib/teact/teact';\nimport usePrevious from '../../../hooks/usePrevious';\n\nimport { ApiChatMember, ApiUser } from '../../../api/types';\n\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport buildClassName from '../../../util/buildClassName';\nimport captureKeyboardListeners from '../../../util/captureKeyboardListeners';\nimport findInViewport from '../../../util/findInViewport';\nimport isFullyVisible from '../../../util/isFullyVisible';\nimport fastSmoothScroll from '../../../util/fastSmoothScroll';\nimport cycleRestrict from '../../../util/cycleRestrict';\n\nimport ListItem from '../../ui/ListItem';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\n\nimport './MentionMenu.scss';\n\nconst VIEWPORT_MARGIN = 8;\nconst SCROLL_MARGIN = 10;\n\nfunction setItemVisible(index: number, containerRef: Record<string, any>) {\n const container = containerRef.current!;\n if (!container || index < 0) {\n return;\n }\n const { visibleIndexes, allElements } = findInViewport(\n container,\n '.chat-item-clickable',\n VIEWPORT_MARGIN,\n true,\n true,\n );\n if (!allElements.length || !allElements[index]) {\n return;\n }\n const first = visibleIndexes[0];\n if (!visibleIndexes.includes(index)\n || (index === first && !isFullyVisible(container, allElements[first]))) {\n const position = index > visibleIndexes[visibleIndexes.length - 1] ? 'start' : 'end';\n fastSmoothScroll(container, allElements[index], position, SCROLL_MARGIN);\n }\n}\n\nexport type OwnProps = {\n isOpen: boolean;\n filter: string;\n onClose: () => void;\n onInsertUserName: (user: ApiUser, forceFocus?: boolean) => void;\n filteredChatMembers?: ApiChatMember[];\n usersById?: Record<number, ApiUser>;\n};\n\nconst MentionMenu: FC<OwnProps> = ({\n isOpen,\n filter,\n onClose,\n onInsertUserName,\n usersById,\n filteredChatMembers,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);\n\n const getSelectedIndex = useCallback((newIndex: number) => {\n if (!filteredChatMembers) {\n return -1;\n }\n const membersCount = filteredChatMembers!.length;\n return cycleRestrict(membersCount, newIndex);\n }, [filteredChatMembers]);\n\n const [selectedMentionIndex, setSelectedMentionIndex] = useState(-1);\n\n const handleArrowKey = useCallback((value: number, e: KeyboardEvent) => {\n e.preventDefault();\n setSelectedMentionIndex((index) => (getSelectedIndex(index + value)));\n }, [setSelectedMentionIndex, getSelectedIndex]);\n\n const handleUserSelect = useCallback((userId: number, forceFocus = false) => {\n const user = usersById && usersById[userId];\n if (!user) {\n return;\n }\n\n onInsertUserName(user, forceFocus);\n }, [usersById, onInsertUserName]);\n\n const handleSelectMention = useCallback((e: KeyboardEvent) => {\n if (filteredChatMembers && filteredChatMembers.length && selectedMentionIndex > -1) {\n const member = filteredChatMembers[selectedMentionIndex];\n if (member) {\n e.preventDefault();\n handleUserSelect(member.userId, true);\n }\n }\n }, [filteredChatMembers, selectedMentionIndex, handleUserSelect]);\n\n useEffect(() => (isOpen ? captureKeyboardListeners({\n onEsc: onClose,\n onUp: (e: KeyboardEvent) => handleArrowKey(-1, e),\n onDown: (e: KeyboardEvent) => handleArrowKey(1, e),\n onEnter: handleSelectMention,\n onTab: handleSelectMention,\n }) : undefined), [isOpen, onClose, handleArrowKey, handleSelectMention]);\n\n useEffect(() => {\n if (filteredChatMembers && !filteredChatMembers.length) {\n onClose();\n }\n }, [filteredChatMembers, onClose]);\n\n useEffect(() => {\n setSelectedMentionIndex(0);\n }, [filter]);\n\n useEffect(() => {\n setItemVisible(selectedMentionIndex, containerRef);\n }, [selectedMentionIndex]);\n\n const prevChatMembers = usePrevious(\n filteredChatMembers && filteredChatMembers.length\n ? filteredChatMembers\n : undefined,\n shouldRender,\n );\n const renderedChatMembers = filteredChatMembers && !filteredChatMembers.length\n ? prevChatMembers\n : filteredChatMembers;\n\n if (!shouldRender || (renderedChatMembers && !renderedChatMembers.length)) {\n return undefined;\n }\n\n const className = buildClassName(\n 'MentionMenu custom-scroll',\n transitionClassNames,\n );\n\n return (\n <div className={className} ref={containerRef}>\n {renderedChatMembers && renderedChatMembers.map(({ userId }, index) => (\n <ListItem\n key={userId}\n className=\"chat-item-clickable scroll-item\"\n onClick={() => handleUserSelect(userId)}\n focus={selectedMentionIndex === index}\n >\n <PrivateChatInfo\n userId={userId}\n avatarSize=\"small\"\n withHandle\n />\n </ListItem>\n ))}\n </div>\n );\n};\n\nexport default memo(MentionMenu);\n","export default function findInViewport(\n container: HTMLElement,\n selectorOrElements: string | NodeListOf<HTMLElement>,\n margin = 0,\n isDense = false,\n shouldContainBottom = false,\n) {\n const viewportY1 = container.scrollTop;\n const viewportY2 = viewportY1 + container.offsetHeight;\n const allElements = typeof selectorOrElements === 'string'\n ? container.querySelectorAll<HTMLElement>(selectorOrElements)\n : selectorOrElements;\n const { length } = allElements;\n const visibleIndexes: number[] = [];\n let isFound = false;\n\n for (let i = 0; i < length; i++) {\n const element = allElements[i];\n const y1 = element.offsetTop;\n const y2 = y1 + element.offsetHeight;\n const isVisible = shouldContainBottom\n ? y2 >= viewportY1 - margin && y2 <= viewportY2 + margin\n : y1 <= viewportY2 + margin && y2 >= viewportY1 - margin;\n\n if (isVisible) {\n visibleIndexes.push(i);\n isFound = true;\n } else if (isFound && !isDense) {\n break;\n }\n }\n\n return { allElements, visibleIndexes };\n}\n","import React, {\n FC, memo, useCallback, useEffect,\n} from '../../../lib/teact/teact';\n\nimport { ApiAttachment, ApiChatMember, ApiUser } from '../../../api/types';\nimport { EDITABLE_INPUT_MODAL_ID } from '../../../config';\n\nimport { getFileExtension } from '../../common/helpers/documentInfo';\nimport captureEscKeyListener from '../../../util/captureEscKeyListener';\nimport usePrevious from '../../../hooks/usePrevious';\nimport useMentionMenu from './hooks/useMentionMenu';\nimport useLang from '../../../hooks/useLang';\n\nimport Button from '../../ui/Button';\nimport Modal from '../../ui/Modal';\nimport File from '../../common/File';\nimport MessageInput from './MessageInput';\nimport MentionMenu from './MentionMenu';\n\nimport './AttachmentModal.scss';\n\nexport type OwnProps = {\n attachments: ApiAttachment[];\n caption: string;\n canSuggestMembers?: boolean;\n currentUserId?: number;\n groupChatMembers?: ApiChatMember[];\n usersById?: Record<number, ApiUser>;\n onCaptionUpdate: (html: string) => void;\n onSend: () => void;\n onClear: () => void;\n};\n\nconst AttachmentModal: FC<OwnProps> = ({\n attachments,\n caption,\n canSuggestMembers,\n groupChatMembers,\n currentUserId,\n usersById,\n onCaptionUpdate,\n onSend,\n onClear,\n}) => {\n const prevAttachments = usePrevious(attachments);\n const renderingAttachments = attachments.length ? attachments : prevAttachments;\n const isOpen = Boolean(attachments.length);\n\n const {\n isMentionMenuOpen, mentionFilter,\n closeMentionMenu, insertMention,\n mentionFilteredMembers,\n } = useMentionMenu(\n canSuggestMembers && isOpen,\n caption,\n onCaptionUpdate,\n EDITABLE_INPUT_MODAL_ID,\n groupChatMembers,\n currentUserId,\n usersById,\n );\n\n useEffect(() => (isOpen ? captureEscKeyListener(onClear) : undefined), [isOpen, onClear]);\n\n const sendAttachments = useCallback(() => {\n if (isOpen) {\n onSend();\n }\n }, [isOpen, onSend]);\n\n const lang = useLang();\n\n if (!renderingAttachments) {\n return undefined;\n }\n\n const areAllPhotos = renderingAttachments.every((a) => a.mimeType.startsWith('image/'));\n const areAllVideos = renderingAttachments.every((a) => a.mimeType.startsWith('video/'));\n\n let title = '';\n if (areAllPhotos) {\n title = renderingAttachments.length === 1 ? 'Send Photo' : `Send ${renderingAttachments.length} Photos`;\n } else if (areAllVideos) {\n title = renderingAttachments.length === 1 ? 'Send Video' : `Send ${renderingAttachments.length} Videos`;\n } else {\n title = renderingAttachments.length === 1 ? 'Send File' : `Send ${renderingAttachments.length} Files`;\n }\n\n const isQuick = renderingAttachments.every((a) => a.quick);\n\n function renderHeader() {\n if (!renderingAttachments) {\n return undefined;\n }\n\n return (\n <div className=\"modal-header-condensed\">\n <Button round color=\"translucent\" size=\"smaller\" ariaLabel=\"Cancel attachments\" onClick={onClear}>\n <i className=\"icon-close\" />\n </Button>\n <div className=\"modal-title\">{title}</div>\n <Button\n color=\"primary\"\n size=\"smaller\"\n className=\"modal-action-button\"\n onClick={sendAttachments}\n >\n {lang('Send')}\n </Button>\n </div>\n );\n }\n\n return (\n <Modal isOpen={isOpen} onClose={onClear} header={renderHeader()} className=\"AttachmentModal\">\n {isQuick ? (\n <div className=\"media-wrapper custom-scroll\">\n {renderingAttachments.map((attachment) => (\n attachment.mimeType.startsWith('image/')\n ? <img src={attachment.blobUrl} alt=\"\" />\n : <video src={attachment.blobUrl} autoPlay muted loop />\n ))}\n </div>\n ) : (\n <div className=\"document-wrapper custom-scroll\">\n {renderingAttachments.map((attachment) => (\n <File\n name={attachment.filename}\n extension={getFileExtension(attachment.filename, attachment.mimeType)}\n previewData={attachment.previewBlobUrl}\n size={attachment.size}\n smaller\n />\n ))}\n </div>\n )}\n\n <div className=\"attachment-caption-wrapper\">\n <MentionMenu\n isOpen={isMentionMenuOpen}\n onClose={closeMentionMenu}\n filter={mentionFilter}\n onInsertUserName={insertMention}\n filteredChatMembers={mentionFilteredMembers}\n usersById={usersById}\n />\n <MessageInput\n id=\"caption-input-text\"\n html={caption}\n editableInputId={EDITABLE_INPUT_MODAL_ID}\n placeholder={lang('Caption')}\n onUpdate={onCaptionUpdate}\n onSend={onSend}\n shouldSetFocus={isOpen}\n />\n </div>\n </Modal>\n );\n};\n\nexport default memo(AttachmentModal);\n","import { ChangeEvent, RefObject } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState,\n} from '../../../lib/teact/teact';\n\nimport { ApiNewPoll } from '../../../api/types';\n\nimport captureEscKeyListener from '../../../util/captureEscKeyListener';\nimport parseMessageInput from './helpers/parseMessageInput';\nimport useLang from '../../../hooks/useLang';\n\nimport Button from '../../ui/Button';\nimport Modal from '../../ui/Modal';\nimport InputText from '../../ui/InputText';\nimport Checkbox from '../../ui/Checkbox';\nimport RadioGroup from '../../ui/RadioGroup';\n\nimport './PollModal.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n onSend: (pollSummary: ApiNewPoll) => void;\n onClear: () => void;\n};\n\nconst MAX_LIST_HEIGHT = 320;\nconst MAX_OPTIONS_COUNT = 10;\nconst MAX_OPTION_LENGTH = 100;\nconst MAX_QUESTION_LENGTH = 255;\nconst MAX_SOLUTION_LENGTH = 200;\n\nconst PollModal: FC<OwnProps> = ({ isOpen, onSend, onClear }) => {\n // eslint-disable-next-line no-null/no-null\n const questionInputRef = useRef<HTMLInputElement>(null);\n // eslint-disable-next-line no-null/no-null\n const optionsListRef = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const solutionRef = useRef<HTMLDivElement>(null);\n\n const [question, setQuestion] = useState<string>('');\n const [options, setOptions] = useState<string[]>(['']);\n const [isAnonymous, setIsAnonymous] = useState(true);\n const [isMultipleAnswers, setIsMultipleAnswers] = useState(false);\n const [isQuizMode, setIsQuizMode] = useState(false);\n const [solution, setSolution] = useState<string>();\n const [correctOption, setCorrectOption] = useState<string>();\n const [hasErrors, setHasErrors] = useState<boolean>(false);\n\n const focusInput = useCallback((ref: RefObject<HTMLInputElement>) => {\n if (isOpen && ref.current) {\n ref.current.focus();\n }\n }, [isOpen]);\n\n useEffect(() => (isOpen ? captureEscKeyListener(onClear) : undefined), [isOpen, onClear]);\n useEffect(() => {\n if (!isOpen) {\n setQuestion('');\n setOptions(['']);\n setIsAnonymous(true);\n setIsMultipleAnswers(false);\n setIsQuizMode(false);\n setSolution('');\n setCorrectOption('');\n setHasErrors(false);\n }\n }, [isOpen]);\n\n useEffect(() => focusInput(questionInputRef), [focusInput, isOpen]);\n\n useLayoutEffect(() => {\n const solutionEl = solutionRef.current;\n\n if (solutionEl && solution !== solutionEl.innerHTML) {\n solutionEl.innerHTML = solution;\n }\n }, [solution]);\n\n const addNewOption = useCallback((newOptions: string[] = []) => {\n setOptions([...newOptions, '']);\n requestAnimationFrame(() => {\n const list = optionsListRef.current;\n if (!list) {\n return;\n }\n\n list.classList.toggle('overflown', list.scrollHeight > MAX_LIST_HEIGHT);\n list.scrollTo({ top: list.scrollHeight, behavior: 'smooth' });\n });\n }, []);\n\n const handleCreate = useCallback(() => {\n setHasErrors(false);\n if (!isOpen) {\n return;\n }\n\n const questionTrimmed = question.trim().substring(0, MAX_QUESTION_LENGTH);\n const optionsTrimmed = options.map((o) => o.trim().substring(0, MAX_OPTION_LENGTH)).filter((o) => o.length);\n\n if (!questionTrimmed || optionsTrimmed.length < 2) {\n setQuestion(questionTrimmed);\n if (optionsTrimmed.length) {\n if (optionsTrimmed.length < 2) {\n addNewOption(optionsTrimmed);\n } else {\n setOptions(optionsTrimmed);\n }\n } else {\n addNewOption();\n }\n setHasErrors(true);\n return;\n }\n\n if (isQuizMode && (!correctOption || !optionsTrimmed[Number(correctOption)])) {\n setHasErrors(true);\n return;\n }\n\n const answers = optionsTrimmed\n .map((text, index) => ({\n text: text.trim(),\n option: String(index),\n ...(String(index) === correctOption && { correct: true }),\n }));\n\n const payload: ApiNewPoll = {\n summary: {\n question: questionTrimmed,\n answers,\n ...(!isAnonymous && { isPublic: true }),\n ...(isMultipleAnswers && { multipleChoice: true }),\n ...(isQuizMode && { quiz: true }),\n },\n };\n\n if (isQuizMode) {\n const { text, entities } = (solution && parseMessageInput(solution.substring(0, MAX_SOLUTION_LENGTH))) || {};\n\n payload.quiz = {\n correctAnswers: [correctOption],\n ...(text && { solution: text }),\n ...(entities && { solutionEntities: entities }),\n };\n }\n\n onSend(payload);\n }, [\n isOpen,\n question,\n options,\n isQuizMode,\n correctOption,\n isAnonymous,\n isMultipleAnswers,\n onSend,\n addNewOption,\n solution,\n ]);\n\n const updateOption = useCallback((index: number, text: string) => {\n const newOptions = [...options];\n newOptions[index] = text;\n if (newOptions[newOptions.length - 1].trim().length && newOptions.length < MAX_OPTIONS_COUNT) {\n addNewOption(newOptions);\n } else {\n setOptions(newOptions);\n }\n }, [options, addNewOption]);\n\n const removeOption = useCallback((index: number) => {\n const newOptions = [...options];\n newOptions.splice(index, 1);\n setOptions(newOptions);\n requestAnimationFrame(() => {\n if (!optionsListRef.current) {\n return;\n }\n\n optionsListRef.current.classList.toggle('overflown', optionsListRef.current.scrollHeight > MAX_LIST_HEIGHT);\n });\n }, [options]);\n\n const handleCorrectOptionChange = useCallback((newValue: string) => {\n setCorrectOption(newValue);\n }, [setCorrectOption]);\n\n const handleIsAnonymousChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setIsAnonymous(e.target.checked);\n }, []);\n\n const handleMultipleAnswersChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setIsMultipleAnswers(e.target.checked);\n }, []);\n\n const handleQuizModeChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setIsQuizMode(e.target.checked);\n }, []);\n\n const handleKeyPress = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.keyCode === 13) {\n handleCreate();\n }\n }, [handleCreate]);\n\n const getQuestionError = useCallback(() => {\n if (hasErrors && !question.trim().length) {\n return 'Please enter the question';\n }\n\n return undefined;\n }, [hasErrors, question]);\n\n const getOptionsError = useCallback((index: number) => {\n const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length);\n if (hasErrors && optionsTrimmed.length < 2 && !options[index].trim().length) {\n return 'Please enter at least two options';\n }\n return undefined;\n }, [hasErrors, options]);\n\n const lang = useLang();\n\n function renderHeader() {\n return (\n <div className=\"modal-header-condensed\">\n <Button round color=\"translucent\" size=\"smaller\" ariaLabel=\"Cancel poll creation\" onClick={onClear}>\n <i className=\"icon-close\" />\n </Button>\n <div className=\"modal-title\">{lang('NewPoll')}</div>\n <Button\n color=\"primary\"\n size=\"smaller\"\n className=\"modal-action-button\"\n onClick={handleCreate}\n >\n {lang('Create')}\n </Button>\n </div>\n );\n }\n\n function renderOptions() {\n return options.map((option, index) => (\n <div className=\"option-wrapper\">\n <InputText\n label={index !== options.length - 1 || options.length === MAX_OPTIONS_COUNT\n ? `Option ${index + 1}`\n : 'Add an Option'}\n error={getOptionsError(index)}\n value={option}\n onChange={(e) => updateOption(index, e.currentTarget.value)}\n onKeyPress={handleKeyPress}\n />\n {index !== options.length - 1 && (\n <Button\n className=\"option-remove-button\"\n round\n color=\"translucent\"\n size=\"smaller\"\n ariaLabel=\"Remove option\"\n onClick={() => removeOption(index)}\n >\n <i className=\"icon-close\" />\n </Button>\n )}\n </div>\n ));\n }\n\n function renderRadioOptions() {\n return renderOptions()\n .map((label, index) => ({ value: String(index), label, hidden: index === options.length - 1 }));\n }\n\n function renderQuizNoOptionError() {\n const optionsTrimmed = options.map((o) => o.trim()).filter((o) => o.length);\n\n return isQuizMode && (!correctOption || !optionsTrimmed[Number(correctOption)]) && (\n <p className=\"error\">\n Please choose the correct answer\n </p>\n );\n }\n\n return (\n <Modal isOpen={isOpen} onClose={onClear} header={renderHeader()} className=\"PollModal\">\n <InputText\n ref={questionInputRef}\n label={lang('AskAQuestion')}\n value={question}\n error={getQuestionError()}\n onChange={(e) => setQuestion(e.currentTarget.value)}\n onKeyPress={handleKeyPress}\n />\n <div className=\"options-divider\" />\n\n <div className=\"options-list custom-scroll\" ref={optionsListRef}>\n <h3 className=\"options-header\">Options</h3>\n\n {hasErrors && renderQuizNoOptionError()}\n {isQuizMode ? (\n <RadioGroup\n name=\"correctOption\"\n options={renderRadioOptions()}\n onChange={handleCorrectOptionChange}\n />\n ) : (\n renderOptions()\n )}\n\n </div>\n\n <div className=\"options-divider\" />\n\n <div className=\"quiz-mode\">\n <Checkbox\n label={lang('PollAnonymous')}\n checked={isAnonymous}\n onChange={handleIsAnonymousChange}\n />\n <Checkbox\n label={lang('PollMultiple')}\n checked={isMultipleAnswers}\n disabled={isQuizMode}\n onChange={handleMultipleAnswersChange}\n />\n <Checkbox\n label={lang('PollQuiz')}\n checked={isQuizMode}\n disabled={isMultipleAnswers}\n onChange={handleQuizModeChange}\n />\n {isQuizMode && (\n <>\n <h3 className=\"options-header\">Solution</h3>\n <div\n ref={solutionRef}\n className=\"form-control\"\n contentEditable\n onChange={(e) => setSolution(e.currentTarget.innerHTML)}\n />\n <div className=\"note\">\n Users will see this comment after choosing a wrong answer, good for educational purposes.\n </div>\n </>\n )}\n </div>\n </Modal>\n );\n};\n\nexport default memo(PollModal);\n","import { useCallback, useEffect, useRef } from '../lib/teact/teact';\n\nimport { IS_TOUCH_ENV } from '../util/environment';\n\nconst MENU_CLOSE_TIMEOUT = 250;\nlet closeTimeout: number | undefined;\n\nexport default function useMouseInside(\n isOpen: boolean, onClose: NoneToVoidFunction, menuCloseTimeout = MENU_CLOSE_TIMEOUT,\n) {\n const isMouseInside = useRef(false);\n\n useEffect(() => {\n if (closeTimeout) {\n clearTimeout(closeTimeout);\n closeTimeout = undefined;\n }\n\n if (isOpen && !IS_TOUCH_ENV) {\n closeTimeout = window.setTimeout(() => {\n if (!isMouseInside.current) {\n onClose();\n }\n }, menuCloseTimeout * 2);\n }\n }, [isOpen, menuCloseTimeout, onClose]);\n\n const handleMouseEnter = useCallback(() => {\n isMouseInside.current = true;\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n isMouseInside.current = false;\n\n if (closeTimeout) {\n clearTimeout(closeTimeout);\n closeTimeout = undefined;\n }\n\n closeTimeout = window.setTimeout(() => {\n if (!isMouseInside.current) {\n onClose();\n }\n }, menuCloseTimeout);\n }, [menuCloseTimeout, onClose]);\n\n return [handleMouseEnter, handleMouseLeave];\n}\n","import React, { FC, memo, useCallback } from '../../../lib/teact/teact';\n\nimport { IS_EMOJI_SUPPORTED } from '../../../util/environment';\n\nimport './EmojiButton.scss';\n\ntype OwnProps = {\n emoji: Emoji;\n onClick: (emoji: string, name: string) => void;\n};\n\nconst EmojiButton: FC<OwnProps> = ({ emoji, onClick }) => {\n const handleClick = useCallback(() => {\n onClick(emoji.native, emoji.id);\n }, [emoji, onClick]);\n\n return (\n <div\n className=\"EmojiButton\"\n onClick={handleClick}\n title={emoji.colons}\n >\n {IS_EMOJI_SUPPORTED ? emoji.native : <img src={`/img-apple-64/${emoji.image}.png`} alt=\"\" loading=\"lazy\" />}\n </div>\n );\n};\n\nexport default memo(EmojiButton);\n","import React, { FC, memo, useRef } from '../../../lib/teact/teact';\n\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport buildClassName from '../../../util/buildClassName';\nimport windowSize from '../../../util/windowSize';\nimport { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport useLang from '../../../hooks/useLang';\n\nimport EmojiButton from './EmojiButton';\n\nconst EMOJIS_PER_ROW_ON_DESKTOP = 9;\nconst EMOJI_MARGIN = 4;\nconst MOBILE_CONTAINER_PADDING = 8;\nconst EMOJI_SIZE = 40;\n\ntype OwnProps = {\n category: EmojiCategory;\n index: number;\n allEmojis: AllEmojis;\n observeIntersection: ObserveFn;\n shouldRender: boolean;\n onEmojiSelect: (emoji: string, name: string) => void;\n};\n\nconst EmojiCategory: FC<OwnProps> = ({\n category, index, allEmojis, observeIntersection, shouldRender, onEmojiSelect,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n\n useOnIntersect(ref, observeIntersection);\n\n const { transitionClassNames } = useShowTransition(shouldRender, undefined, undefined, 'slow');\n\n const lang = useLang();\n\n const emojisPerRow = IS_MOBILE_SCREEN\n ? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (EMOJI_SIZE + EMOJI_MARGIN))\n : EMOJIS_PER_ROW_ON_DESKTOP;\n const height = Math.ceil(category.emojis.length / emojisPerRow) * (EMOJI_SIZE + EMOJI_MARGIN);\n\n return (\n <div\n ref={ref}\n key={category.id}\n id={`emoji-category-${index}`}\n className=\"symbol-set\"\n >\n <p className=\"symbol-set-name\">{lang(category.id === 'recent' ? 'RecentStickers' : `Emoji${index}`)}</p>\n <div\n className={buildClassName('symbol-set-container', transitionClassNames)}\n // @ts-ignore\n style={`height: ${height}px;`}\n >\n {shouldRender && category.emojis.map((name) => {\n const emoji = allEmojis[name];\n // Some emojis have multiple skins and are represented as an Object with emojis for all skins.\n // For now, we select only the first emoji with 'neutral' skin.\n const displayedEmoji = 'id' in emoji ? emoji : emoji[1];\n\n return (\n <EmojiButton\n key={displayedEmoji.id}\n emoji={displayedEmoji}\n onClick={onEmojiSelect}\n />\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default memo(EmojiCategory);\n","import React, {\n FC, useState, useEffect, memo, useRef, useMemo, useCallback,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalState, GlobalActions } from '../../../global/types';\n\nimport { MENU_TRANSITION_DURATION } from '../../../config';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport {\n EmojiModule,\n EmojiRawData,\n EmojiData,\n uncompressEmoji,\n} from '../../../util/emoji';\nimport fastSmoothScroll from '../../../util/fastSmoothScroll';\nimport buildClassName from '../../../util/buildClassName';\nimport { pick } from '../../../util/iteratees';\nimport fastSmoothScrollHorizontal from '../../../util/fastSmoothScrollHorizontal';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\nimport { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';\nimport useHorizontalScroll from '../../../hooks/useHorizontalScroll';\nimport useLang from '../../../hooks/useLang';\n\nimport Button from '../../ui/Button';\nimport Loading from '../../ui/Loading';\nimport EmojiCategory from './EmojiCategory';\n\nimport './EmojiPicker.scss';\n\ntype OwnProps = {\n className?: string;\n onEmojiSelect: (emoji: string) => void;\n};\n\ntype StateProps = Pick<GlobalState, 'recentEmojis'>;\ntype DispatchProps = Pick<GlobalActions, 'addRecentEmoji'>;\ntype EmojiCategoryData = { id: string; name: string; emojis: string[] };\n\nconst ICONS_BY_CATEGORY: Record<string, string> = {\n recent: 'icon-recent',\n people: 'icon-smile',\n nature: 'icon-animals',\n foods: 'icon-eats',\n activity: 'icon-sport',\n places: 'icon-car',\n objects: 'icon-lamp',\n symbols: 'icon-language',\n flags: 'icon-flag',\n};\n\nconst OPEN_ANIMATION_DELAY = 200;\n// Only a few categories are above this height.\nconst SMOOTH_SCROLL_DISTANCE = 800;\nconst FOCUS_MARGIN = 50;\nconst HEADER_BUTTON_WIDTH = 42; // px. Includes margins\nconst INTERSECTION_THROTTLE = 200;\n\nconst categoryIntersections: boolean[] = [];\n\nlet emojiDataPromise: Promise<EmojiModule>;\nlet emojiRawData: EmojiRawData;\nlet emojiData: EmojiData;\n\nconst EmojiPicker: FC<OwnProps & StateProps & DispatchProps> = ({\n className, onEmojiSelect, recentEmojis, addRecentEmoji,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const headerRef = useRef<HTMLDivElement>(null);\n\n const [categories, setCategories] = useState<EmojiCategoryData[]>();\n const [emojis, setEmojis] = useState<AllEmojis>();\n const [activeCategoryIndex, setActiveCategoryIndex] = useState(0);\n\n const { observe: observeIntersection } = useIntersectionObserver({\n rootRef: containerRef,\n throttleMs: INTERSECTION_THROTTLE,\n }, (entries) => {\n entries.forEach((entry) => {\n const { id } = entry.target as HTMLDivElement;\n if (!id || !id.startsWith('emoji-category-')) {\n return;\n }\n\n const index = Number(id.replace('emoji-category-', ''));\n categoryIntersections[index] = entry.isIntersecting;\n });\n\n const intersectingWithIndexes = categoryIntersections\n .map((isIntersecting, index) => ({ index, isIntersecting }))\n .filter(({ isIntersecting }) => isIntersecting);\n\n if (!intersectingWithIndexes.length) {\n return;\n }\n\n setActiveCategoryIndex(intersectingWithIndexes[Math.floor(intersectingWithIndexes.length / 2)].index);\n });\n\n useHorizontalScroll(headerRef, !IS_MOBILE_SCREEN);\n\n // Scroll header when active set updates\n useEffect(() => {\n if (!categories) {\n return;\n }\n\n const header = headerRef.current;\n if (!header) {\n return;\n }\n\n const newLeft = activeCategoryIndex * HEADER_BUTTON_WIDTH - header.offsetWidth / 2 + HEADER_BUTTON_WIDTH / 2;\n\n fastSmoothScrollHorizontal(header, newLeft);\n }, [categories, activeCategoryIndex]);\n\n const lang = useLang();\n\n const allCategories = useMemo(() => {\n if (!categories) {\n return MEMO_EMPTY_ARRAY;\n }\n const themeCategories = [...categories];\n if (recentEmojis && recentEmojis.length) {\n themeCategories.unshift({\n id: 'recent',\n name: lang('RecentStickers'),\n emojis: recentEmojis,\n });\n }\n\n return themeCategories;\n }, [categories, lang, recentEmojis]);\n\n // Initialize data on first render.\n useEffect(() => {\n setTimeout(() => {\n const exec = () => {\n setCategories(emojiData.categories);\n\n setEmojis(emojiData.emojis as AllEmojis);\n };\n\n if (emojiData) {\n exec();\n } else {\n ensureEmojiData()\n .then(exec);\n }\n }, OPEN_ANIMATION_DELAY);\n }, []);\n\n const selectCategory = useCallback((index: number) => {\n setActiveCategoryIndex(index);\n const categoryEl = document.getElementById(`emoji-category-${index}`)!;\n fastSmoothScroll(containerRef.current!, categoryEl, 'start', FOCUS_MARGIN, SMOOTH_SCROLL_DISTANCE);\n }, []);\n\n const handleEmojiSelect = useCallback((emoji: string, name: string) => {\n onEmojiSelect(emoji);\n addRecentEmoji({ emoji: name });\n }, [addRecentEmoji, onEmojiSelect]);\n\n const canRenderContents = useAsyncRendering([], MENU_TRANSITION_DURATION);\n\n function renderCategoryButton(category: EmojiCategoryData, index: number) {\n const icon = ICONS_BY_CATEGORY[category.id];\n\n return icon && (\n <Button\n className={`symbol-set-button ${index === activeCategoryIndex ? 'activated' : ''}`}\n round\n faded\n color=\"translucent\"\n onClick={() => selectCategory(index)}\n ariaLabel={category.name}\n >\n <i className={icon} />\n </Button>\n );\n }\n\n const containerClassName = buildClassName('EmojiPicker', className);\n\n if (!emojis || !canRenderContents) {\n return (\n <div className={containerClassName}>\n <Loading />\n </div>\n );\n }\n\n return (\n <div className={containerClassName}>\n <div ref={headerRef} className=\"EmojiPicker-header\">\n {allCategories.map(renderCategoryButton)}\n </div>\n <div ref={containerRef} className=\"EmojiPicker-main no-selection no-scrollbar\">\n {allCategories.map((category, i) => (\n <EmojiCategory\n category={category}\n index={i}\n allEmojis={emojis}\n observeIntersection={observeIntersection}\n shouldRender={activeCategoryIndex >= i - 1 && activeCategoryIndex <= i + 1}\n onEmojiSelect={handleEmojiSelect}\n />\n ))}\n </div>\n </div>\n );\n};\n\nasync function ensureEmojiData() {\n if (!emojiDataPromise) {\n emojiDataPromise = import('emoji-data-ios/emoji-data.json') as unknown as Promise<EmojiModule>;\n emojiRawData = (await emojiDataPromise).default;\n\n emojiData = uncompressEmoji(emojiRawData);\n }\n\n return emojiDataPromise;\n}\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => pick(global, ['recentEmojis']),\n (setGlobal, actions): DispatchProps => pick(actions, ['addRecentEmoji']),\n)(EmojiPicker));\n","import React, { FC, memo, useRef } from '../../../lib/teact/teact';\n\nimport { ApiSticker } from '../../../api/types';\nimport { StickerSetOrRecent } from '../../../types';\nimport { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';\n\nimport { STICKER_SIZE_PICKER } from '../../../config';\nimport { IS_MOBILE_SCREEN } from '../../../util/environment';\nimport windowSize from '../../../util/windowSize';\nimport StickerButton from '../../common/StickerButton';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport buildClassName from '../../../util/buildClassName';\n\ntype OwnProps = {\n stickerSet: StickerSetOrRecent;\n loadAndPlay: boolean;\n index: number;\n observeIntersection: ObserveFn;\n shouldRender: boolean;\n onStickerSelect: (sticker: ApiSticker) => void;\n onStickerUnfave: (sticker: ApiSticker) => void;\n};\n\nconst STICKERS_PER_ROW_ON_DESKTOP = 5;\nconst STICKER_MARGIN = IS_MOBILE_SCREEN ? 8 : 16;\nconst MOBILE_CONTAINER_PADDING = 8;\n\nconst StickerSet: FC<OwnProps> = ({\n stickerSet,\n loadAndPlay,\n index,\n observeIntersection,\n shouldRender,\n onStickerSelect,\n onStickerUnfave,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n\n useOnIntersect(ref, observeIntersection);\n\n const { transitionClassNames } = useShowTransition(shouldRender, undefined, undefined, 'slow');\n\n const stickersPerRow = IS_MOBILE_SCREEN\n ? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (STICKER_SIZE_PICKER + STICKER_MARGIN))\n : STICKERS_PER_ROW_ON_DESKTOP;\n const height = Math.ceil(stickerSet.count / stickersPerRow) * (STICKER_SIZE_PICKER + STICKER_MARGIN);\n\n return (\n <div\n ref={ref}\n key={stickerSet.id}\n id={`sticker-set-${index}`}\n className=\"symbol-set\"\n >\n <p className=\"symbol-set-name\">{stickerSet.title}</p>\n <div\n className={buildClassName('symbol-set-container', transitionClassNames)}\n // @ts-ignore\n style={`height: ${height}px;`}\n >\n {shouldRender && stickerSet.stickers && stickerSet.stickers.map((sticker) => (\n <StickerButton\n key={sticker.id}\n sticker={sticker}\n size={STICKER_SIZE_PICKER}\n observeIntersection={observeIntersection}\n noAnimate={!loadAndPlay}\n onClick={onStickerSelect}\n clickArg={sticker}\n onUnfaveClick={stickerSet.id === 'favorite' ? onStickerUnfave : undefined}\n />\n ))}\n </div>\n </div>\n );\n};\n\nexport default memo(StickerSet);\n","import React, {\n FC, useState, useEffect, memo, useRef, useMemo, useCallback,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiStickerSet, ApiSticker } from '../../../api/types';\nimport { StickerSetOrRecent } from '../../../types';\n\nimport { SLIDE_TRANSITION_DURATION, STICKER_SIZE_PICKER_HEADER } from '../../../config';\nimport { MEMO_EMPTY_ARRAY } from '../../../util/memo';\nimport fastSmoothScroll from '../../../util/fastSmoothScroll';\nimport buildClassName from '../../../util/buildClassName';\nimport { pick } from '../../../util/iteratees';\nimport fastSmoothScrollHorizontal from '../../../util/fastSmoothScrollHorizontal';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\nimport { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';\nimport useHorizontalScroll from '../../../hooks/useHorizontalScroll';\nimport useLang from '../../../hooks/useLang';\n\nimport Loading from '../../ui/Loading';\nimport Button from '../../ui/Button';\nimport StickerButton from '../../common/StickerButton';\nimport StickerSet from './StickerSet';\nimport StickerSetCover from './StickerSetCover';\nimport StickerSetCoverAnimated from './StickerSetCoverAnimated';\n\nimport './StickerPicker.scss';\n\ntype OwnProps = {\n className: string;\n loadAndPlay: boolean;\n canSendStickers: boolean;\n onStickerSelect: (sticker: ApiSticker) => void;\n};\n\ntype StateProps = {\n recentStickers: ApiSticker[];\n favoriteStickers: ApiSticker[];\n stickerSetsById: Record<string, ApiStickerSet>;\n addedSetIds?: string[];\n shouldPlay?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'loadStickerSets' | 'loadRecentStickers' | 'loadFavoriteStickers' |\n 'addRecentSticker' | 'loadAddedStickers' | 'unfaveSticker'\n)>;\n\nconst SMOOTH_SCROLL_DISTANCE = 500;\nconst HEADER_BUTTON_WIDTH = 52; // px (including margin)\nconst STICKER_INTERSECTION_THROTTLE = 200;\n\nconst stickerSetIntersections: boolean[] = [];\n\nconst StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({\n className,\n loadAndPlay,\n canSendStickers,\n recentStickers,\n favoriteStickers,\n addedSetIds,\n stickerSetsById,\n shouldPlay,\n onStickerSelect,\n loadStickerSets,\n loadRecentStickers,\n loadFavoriteStickers,\n loadAddedStickers,\n addRecentSticker,\n unfaveSticker,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const headerRef = useRef<HTMLDivElement>(null);\n const [activeSetIndex, setActiveSetIndex] = useState<number>(0);\n\n const { observe: observeIntersection } = useIntersectionObserver({\n rootRef: containerRef,\n throttleMs: STICKER_INTERSECTION_THROTTLE,\n }, (entries) => {\n entries.forEach((entry) => {\n const { id } = entry.target as HTMLDivElement;\n if (!id || !id.startsWith('sticker-set-')) {\n return;\n }\n\n const index = Number(id.replace('sticker-set-', ''));\n stickerSetIntersections[index] = entry.isIntersecting;\n });\n\n const intersectingWithIndexes = stickerSetIntersections\n .map((isIntersecting, index) => ({ index, isIntersecting }))\n .filter(({ isIntersecting }) => isIntersecting);\n\n if (!intersectingWithIndexes.length) {\n return;\n }\n\n setActiveSetIndex(intersectingWithIndexes[Math.floor(intersectingWithIndexes.length / 2)].index);\n });\n const { observe: observeIntersectionForCovers } = useIntersectionObserver({ rootRef: headerRef });\n\n const lang = useLang();\n\n const areAddedLoaded = Boolean(addedSetIds);\n\n const allSets = useMemo(() => {\n if (!addedSetIds) {\n return MEMO_EMPTY_ARRAY;\n }\n\n return [\n {\n id: 'recent',\n title: lang('RecentStickers'),\n stickers: recentStickers,\n count: recentStickers.length,\n },\n {\n id: 'favorite',\n title: lang('FavoriteStickers'),\n stickers: favoriteStickers,\n count: favoriteStickers.length,\n },\n ...addedSetIds.map((id) => stickerSetsById[id]).filter(Boolean),\n ];\n }, [addedSetIds, lang, recentStickers, favoriteStickers, stickerSetsById]);\n\n const noPopulatedSets = useMemo(() => (\n areAddedLoaded\n && allSets.filter((set) => set.stickers && set.stickers.length).length === 0\n ), [allSets, areAddedLoaded]);\n\n useEffect(() => {\n if (loadAndPlay) {\n loadStickerSets();\n loadRecentStickers();\n loadFavoriteStickers();\n }\n }, [loadAndPlay, loadFavoriteStickers, loadRecentStickers, loadStickerSets]);\n\n useEffect(() => {\n if (addedSetIds && addedSetIds.length) {\n loadAddedStickers();\n }\n }, [addedSetIds, loadAddedStickers]);\n\n useHorizontalScroll(headerRef);\n\n // Scroll container and header when active set changes\n useEffect(() => {\n if (!areAddedLoaded) {\n return;\n }\n\n const header = headerRef.current;\n if (!header) {\n return;\n }\n\n const newLeft = activeSetIndex * HEADER_BUTTON_WIDTH - (header.offsetWidth / 2 - HEADER_BUTTON_WIDTH / 2);\n\n fastSmoothScrollHorizontal(header, newLeft);\n }, [areAddedLoaded, activeSetIndex]);\n\n const selectStickerSet = useCallback((index: number) => {\n setActiveSetIndex(index);\n const stickerSetEl = document.getElementById(`sticker-set-${index}`)!;\n fastSmoothScroll(containerRef.current!, stickerSetEl, 'start', undefined, SMOOTH_SCROLL_DISTANCE);\n }, []);\n\n const handleStickerSelect = useCallback((sticker: ApiSticker) => {\n onStickerSelect(sticker);\n addRecentSticker({ sticker });\n }, [addRecentSticker, onStickerSelect]);\n\n const handleStickerUnfave = useCallback((sticker: ApiSticker) => {\n unfaveSticker({ sticker });\n }, [unfaveSticker]);\n\n const canRenderContents = useAsyncRendering([], SLIDE_TRANSITION_DURATION);\n\n function renderCover(stickerSet: StickerSetOrRecent, index: number) {\n const firstSticker = stickerSet.stickers && stickerSet.stickers[0];\n const buttonClassName = buildClassName(\n 'symbol-set-button sticker-set-button',\n index === activeSetIndex && 'activated',\n );\n\n if (stickerSet.id === 'recent' || stickerSet.id === 'favorite' || stickerSet.hasThumbnail || !firstSticker) {\n return (\n <Button\n key={stickerSet.id}\n className={buttonClassName}\n ariaLabel={stickerSet.title}\n round\n faded={stickerSet.id === 'recent' || stickerSet.id === 'favorite'}\n color=\"translucent\"\n onClick={() => selectStickerSet(index)}\n >\n {stickerSet.id === 'recent' ? (\n <i className=\"icon-recent\" />\n ) : stickerSet.id === 'favorite' ? (\n <i className=\"icon-favorite\" />\n ) : stickerSet.isAnimated ? (\n <StickerSetCoverAnimated\n stickerSet={stickerSet as ApiStickerSet}\n observeIntersection={observeIntersectionForCovers}\n />\n ) : (\n <StickerSetCover\n stickerSet={stickerSet as ApiStickerSet}\n observeIntersection={observeIntersectionForCovers}\n />\n )}\n </Button>\n );\n } else {\n return (\n <StickerButton\n key={stickerSet.id}\n sticker={firstSticker}\n size={STICKER_SIZE_PICKER_HEADER}\n title={stickerSet.title}\n className={buttonClassName}\n observeIntersection={observeIntersectionForCovers}\n onClick={selectStickerSet}\n clickArg={index}\n />\n );\n }\n }\n\n const fullClassName = buildClassName('StickerPicker', className);\n\n if (!areAddedLoaded || !canRenderContents || noPopulatedSets || !canSendStickers) {\n return (\n <div className={fullClassName}>\n {!canSendStickers ? (\n <div className=\"picker-disabled\">Sending stickers is not allowed in this chat.</div>\n ) : noPopulatedSets ? (\n <div className=\"picker-disabled\">You have no saved Stickers.</div>\n ) : (\n <Loading />\n )}\n </div>\n );\n }\n\n return (\n <div className={fullClassName}>\n <div\n ref={headerRef}\n className=\"StickerPicker-header no-selection no-scrollbar\"\n >\n {allSets.map(renderCover)}\n </div>\n <div ref={containerRef} className=\"StickerPicker-main no-scrollbar\">\n {allSets.map((stickerSet, i) => (\n <StickerSet\n key={stickerSet.id}\n stickerSet={stickerSet}\n loadAndPlay={Boolean(shouldPlay && loadAndPlay)}\n index={i}\n observeIntersection={observeIntersection}\n shouldRender={activeSetIndex >= i - 1 && activeSetIndex <= i + 1}\n onStickerSelect={handleStickerSelect}\n onStickerUnfave={handleStickerUnfave}\n />\n ))}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const {\n setsById,\n added,\n recent,\n favorite,\n } = global.stickers;\n\n return {\n recentStickers: recent.stickers,\n favoriteStickers: favorite.stickers,\n stickerSetsById: setsById,\n addedSetIds: added.setIds,\n shouldPlay: global.settings.byKey.shouldLoopStickers,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadStickerSets',\n 'loadRecentStickers',\n 'loadFavoriteStickers',\n 'loadAddedStickers',\n 'addRecentSticker',\n 'unfaveSticker',\n ]),\n)(StickerPicker));\n","import React, {\n FC, memo, useCallback, useRef,\n} from '../../lib/teact/teact';\n\nimport { ApiMediaFormat, ApiVideo } from '../../api/types';\n\nimport buildClassName from '../../util/buildClassName';\nimport { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';\nimport useMedia from '../../hooks/useMedia';\nimport useTransitionForMedia from '../../hooks/useTransitionForMedia';\nimport useBlur from '../../hooks/useBlur';\nimport useVideoCleanup from '../../hooks/useVideoCleanup';\nimport useBuffering from '../../hooks/useBuffering';\n\nimport Spinner from '../ui/Spinner';\n\nimport './GifButton.scss';\n\ntype OwnProps = {\n gif: ApiVideo;\n observeIntersection: ObserveFn;\n isDisabled?: boolean;\n onClick: (gif: ApiVideo) => void;\n};\n\nconst GifButton: FC<OwnProps> = ({\n gif, observeIntersection, isDisabled, onClick,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const ref = useRef<HTMLDivElement>(null);\n // eslint-disable-next-line no-null/no-null\n const videoRef = useRef<HTMLVideoElement>(null);\n\n const localMediaHash = `gif${gif.id}`;\n const isIntersecting = useIsIntersecting(ref, observeIntersection);\n const loadAndPlay = isIntersecting && !isDisabled;\n const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !loadAndPlay, ApiMediaFormat.BlobUrl);\n const thumbDataUri = useBlur(gif.thumbnail && gif.thumbnail.dataUri, Boolean(previewBlobUrl));\n const previewData = previewBlobUrl || thumbDataUri;\n const videoData = useMedia(localMediaHash, !loadAndPlay, ApiMediaFormat.BlobUrl);\n const shouldRenderVideo = Boolean(loadAndPlay && videoData);\n const { transitionClassNames } = useTransitionForMedia(previewData || videoData, 'slow');\n const { isBuffered, bufferingHandlers } = useBuffering(true);\n const shouldRenderSpinner = loadAndPlay && !isBuffered;\n\n useVideoCleanup(videoRef, [shouldRenderVideo]);\n\n const handleClick = useCallback(\n () => onClick({\n ...gif,\n blobUrl: videoData,\n }),\n [onClick, gif, videoData],\n );\n\n const className = buildClassName(\n 'GifButton',\n gif.width && gif.height && gif.width < gif.height ? 'vertical' : 'horizontal',\n transitionClassNames,\n localMediaHash,\n );\n\n return (\n <div\n ref={ref}\n className={className}\n onClick={handleClick}\n >\n {previewData && !shouldRenderVideo && (\n <div\n className=\"preview\"\n // @ts-ignore\n style={`background-image: url(${previewData});`}\n />\n )}\n {shouldRenderVideo && (\n <video\n ref={videoRef}\n autoPlay\n loop\n muted\n playsInline\n preload=\"none\"\n poster={previewData}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...bufferingHandlers}\n >\n <source src={videoData} />\n </video>\n )}\n {shouldRenderSpinner && (\n <Spinner color={previewData ? 'white' : 'black'} />\n )}\n </div>\n );\n};\n\nexport default memo(GifButton);\n","import React, {\n FC, useEffect, memo, useRef,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiVideo } from '../../../api/types';\n\nimport { SLIDE_TRANSITION_DURATION } from '../../../config';\nimport buildClassName from '../../../util/buildClassName';\nimport { pick } from '../../../util/iteratees';\nimport { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';\nimport useAsyncRendering from '../../right/hooks/useAsyncRendering';\n\nimport Loading from '../../ui/Loading';\nimport GifButton from '../../common/GifButton';\n\nimport './GifPicker.scss';\n\ntype OwnProps = {\n className: string;\n loadAndPlay: boolean;\n canSendGifs: boolean;\n onGifSelect: (gif: ApiVideo) => void;\n};\n\ntype StateProps = {\n savedGifs?: ApiVideo[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadSavedGifs'>;\n\nconst INTERSECTION_DEBOUNCE = 300;\n\nconst GifPicker: FC<OwnProps & StateProps & DispatchProps> = ({\n className,\n loadAndPlay,\n canSendGifs,\n savedGifs,\n onGifSelect,\n loadSavedGifs,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n\n const {\n observe: observeIntersection,\n } = useIntersectionObserver({ rootRef: containerRef, debounceMs: INTERSECTION_DEBOUNCE });\n\n useEffect(() => {\n if (loadAndPlay) {\n loadSavedGifs();\n }\n }, [loadAndPlay, loadSavedGifs]);\n\n const canRenderContents = useAsyncRendering([], SLIDE_TRANSITION_DURATION);\n\n return (\n <div ref={containerRef} className={buildClassName('GifPicker no-scrollbar', className)}>\n {!canSendGifs ? (\n <div className=\"picker-disabled\">Sending GIFs is not allowed in this chat.</div>\n ) : canRenderContents && savedGifs && savedGifs.length ? (\n savedGifs.map((gif) => (\n <GifButton\n key={gif.id}\n gif={gif}\n observeIntersection={observeIntersection}\n isDisabled={!loadAndPlay}\n onClick={onGifSelect}\n />\n ))\n ) : canRenderContents && savedGifs ? (\n <div className=\"picker-disabled\">No saved GIFs.</div>\n ) : (\n <Loading />\n )}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n return {\n savedGifs: global.gifs.saved.gifs,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadSavedGifs']),\n)(GifPicker));\n","import React, { FC, memo, useCallback } from '../../../lib/teact/teact';\n\nimport Button from '../../ui/Button';\n\ntype OwnProps = {\n activeTab: SymbolMenuTabs;\n onSwitchTab: (tab: SymbolMenuTabs) => void;\n onRemoveSymbol: () => void;\n onSearchOpen: (type: 'stickers' | 'gifs') => void;\n};\n\nexport enum SymbolMenuTabs {\n 'Emoji',\n 'Stickers',\n 'GIFs',\n}\n\n// Getting enum string values for display in Tabs.\n// See: https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings\nexport const SYMBOL_MENU_TAB_TITLES = Object.values(SymbolMenuTabs)\n .filter((value): value is string => typeof value === 'string');\n\nconst SYMBOL_MENU_TAB_ICONS = {\n [SymbolMenuTabs.Emoji]: 'icon-smile',\n [SymbolMenuTabs.Stickers]: 'icon-stickers',\n [SymbolMenuTabs.GIFs]: 'icon-gifs',\n};\n\nconst SymbolMenuFooter: FC<OwnProps> = ({\n activeTab, onSwitchTab, onRemoveSymbol, onSearchOpen,\n}) => {\n function renderTabButton(tab: SymbolMenuTabs) {\n return (\n <Button\n className={`symbol-tab-button ${activeTab === tab ? 'activated' : ''}`}\n onClick={() => onSwitchTab(tab)}\n ariaLabel={SYMBOL_MENU_TAB_TITLES[tab]}\n round\n faded\n color=\"translucent\"\n >\n <i className={SYMBOL_MENU_TAB_ICONS[tab]} />\n </Button>\n );\n }\n\n const handleSearchOpen = useCallback(() => {\n onSearchOpen(activeTab === SymbolMenuTabs.Stickers ? 'stickers' : 'gifs');\n }, [activeTab, onSearchOpen]);\n\n function stopPropagation(event: any) {\n event.stopPropagation();\n }\n\n return (\n <div className=\"SymbolMenu-footer\" onClick={stopPropagation}>\n {activeTab !== SymbolMenuTabs.Emoji && (\n <Button\n className=\"symbol-search-button\"\n ariaLabel={activeTab === SymbolMenuTabs.Stickers ? 'Search Stickers' : 'Search GIFs'}\n round\n faded\n color=\"translucent\"\n onClick={handleSearchOpen}\n >\n <i className=\"icon-search\" />\n </Button>\n )}\n\n {renderTabButton(SymbolMenuTabs.Emoji)}\n {renderTabButton(SymbolMenuTabs.Stickers)}\n {renderTabButton(SymbolMenuTabs.GIFs)}\n\n {activeTab === SymbolMenuTabs.Emoji && (\n <Button\n className=\"symbol-delete-button\"\n onClick={onRemoveSymbol}\n ariaLabel=\"Remove Symbol\"\n round\n faded\n color=\"translucent\"\n >\n <i className=\"icon-delete-left\" />\n </Button>\n )}\n </div>\n );\n};\n\nexport default memo(SymbolMenuFooter);\n","import React, {\n FC, memo, useState, useCallback, useEffect, useLayoutEffect,\n} from '../../../lib/teact/teact';\n\nimport { ApiSticker, ApiVideo } from '../../../api/types';\n\nimport { IAllowedAttachmentOptions } from '../../../modules/helpers';\nimport { IS_TOUCH_ENV, IS_MOBILE_SCREEN } from '../../../util/environment';\nimport { fastRaf } from '../../../util/schedulers';\nimport buildClassName from '../../../util/buildClassName';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport useMouseInside from '../../../hooks/useMouseInside';\nimport useLang from '../../../hooks/useLang';\n\nimport Button from '../../ui/Button';\nimport Menu from '../../ui/Menu';\nimport Transition from '../../ui/Transition';\nimport EmojiPicker from './EmojiPicker';\nimport StickerPicker from './StickerPicker';\nimport GifPicker from './GifPicker';\nimport SymbolMenuFooter, { SymbolMenuTabs, SYMBOL_MENU_TAB_TITLES } from './SymbolMenuFooter';\nimport Portal from '../../ui/Portal';\n\nimport './SymbolMenu.scss';\n\nconst ANIMATION_DURATION = 350;\n\nexport type OwnProps = {\n isOpen: boolean;\n allowedAttachmentOptions: IAllowedAttachmentOptions;\n onLoad: () => void;\n onClose: () => void;\n onEmojiSelect: (emoji: string) => void;\n onStickerSelect: (sticker: ApiSticker) => void;\n onGifSelect: (gif: ApiVideo) => void;\n onRemoveSymbol: () => void;\n onSearchOpen: (type: 'stickers' | 'gifs') => void;\n};\n\nlet isActivated = false;\n\nconst SymbolMenu: FC<OwnProps> = ({\n isOpen, allowedAttachmentOptions,\n onLoad, onClose,\n onEmojiSelect, onStickerSelect, onGifSelect,\n onRemoveSymbol, onSearchOpen,\n}) => {\n const [activeTab, setActiveTab] = useState<number>(0);\n\n const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);\n const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);\n\n if (!isActivated && isOpen) {\n isActivated = true;\n }\n\n useEffect(() => {\n onLoad();\n }, [onLoad]);\n\n useLayoutEffect(() => {\n if (!IS_MOBILE_SCREEN) {\n return undefined;\n }\n\n if (isOpen) {\n document.body.classList.add('enable-symbol-menu-transforms');\n document.body.classList.add('is-symbol-menu-open');\n }\n\n return () => {\n if (isOpen) {\n fastRaf(() => {\n document.body.classList.remove('is-symbol-menu-open');\n setTimeout(() => {\n document.body.classList.remove('enable-symbol-menu-transforms');\n }, ANIMATION_DURATION);\n });\n }\n };\n }, [isOpen]);\n\n const handleSearch = useCallback((type: 'stickers' | 'gifs') => {\n onClose();\n onSearchOpen(type);\n }, [onClose, onSearchOpen]);\n\n const lang = useLang();\n\n const { canSendStickers, canSendGifs } = allowedAttachmentOptions;\n\n function renderContent(isActive: boolean, isFrom: boolean) {\n switch (activeTab) {\n case SymbolMenuTabs.Emoji:\n return (\n <EmojiPicker\n className=\"picker-tab\"\n onEmojiSelect={onEmojiSelect}\n />\n );\n case SymbolMenuTabs.Stickers:\n return (\n <StickerPicker\n className=\"picker-tab\"\n loadAndPlay={canSendStickers ? isOpen && (isActive || isFrom) : false}\n canSendStickers={canSendStickers}\n onStickerSelect={onStickerSelect}\n />\n );\n case SymbolMenuTabs.GIFs:\n return (\n <GifPicker\n className=\"picker-tab\"\n loadAndPlay={canSendGifs ? isOpen && (isActive || isFrom) : false}\n canSendGifs={canSendGifs}\n onGifSelect={onGifSelect}\n />\n );\n }\n\n return undefined;\n }\n\n function stopPropagation(event: any) {\n event.stopPropagation();\n }\n\n const content = (\n <>\n <div className=\"SymbolMenu-main\" onClick={stopPropagation}>\n {isActivated && (\n <Transition name=\"slide\" activeKey={activeTab} renderCount={SYMBOL_MENU_TAB_TITLES.length}>\n {renderContent}\n </Transition>\n )}\n </div>\n {IS_MOBILE_SCREEN && (\n <Button\n round\n faded\n color=\"translucent\"\n ariaLabel={lang('Close')}\n className=\"symbol-close-button\"\n size=\"tiny\"\n onClick={onClose}\n >\n <i className=\"icon-close\" />\n </Button>\n )}\n <SymbolMenuFooter\n activeTab={activeTab}\n onSwitchTab={setActiveTab}\n onRemoveSymbol={onRemoveSymbol}\n onSearchOpen={handleSearch}\n />\n </>\n );\n\n if (IS_MOBILE_SCREEN) {\n if (!shouldRender) {\n return undefined;\n }\n\n const className = buildClassName(\n 'SymbolMenu mobile-menu',\n transitionClassNames,\n );\n\n return (\n <Portal>\n <div className={className}>\n {content}\n </div>\n </Portal>\n );\n }\n\n return (\n <Menu\n isOpen={isOpen}\n positionX=\"left\"\n positionY=\"bottom\"\n onClose={onClose}\n className=\"SymbolMenu\"\n onCloseAnimationEnd={onClose}\n onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}\n onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}\n noCloseOnBackdrop={!IS_TOUCH_ENV}\n >\n {content}\n </Menu>\n );\n};\n\nexport default memo(SymbolMenu);\n","import React, { FC, memo, useCallback } from '../../../lib/teact/teact';\n\nimport { CONTENT_TYPES_FOR_QUICK_UPLOAD } from '../../../config';\nimport { IS_TOUCH_ENV } from '../../../util/environment';\nimport { openSystemFilesDialog } from '../../../util/systemFilesDialog';\nimport { IAllowedAttachmentOptions } from '../../../modules/helpers';\nimport useMouseInside from '../../../hooks/useMouseInside';\nimport useLang from '../../../hooks/useLang';\n\nimport Menu from '../../ui/Menu';\nimport MenuItem from '../../ui/MenuItem';\n\nimport './AttachMenu.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n allowedAttachmentOptions: IAllowedAttachmentOptions;\n onFileSelect: (files: File[], isQuick: boolean) => void;\n onPollCreate: () => void;\n onClose: () => void;\n};\n\nconst AttachMenu: FC<OwnProps> = ({\n isOpen, allowedAttachmentOptions, onFileSelect, onPollCreate, onClose,\n}) => {\n const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);\n\n const handleFileSelect = useCallback((e: Event, isQuick: boolean) => {\n const { files } = e.target as HTMLInputElement;\n\n if (files && files.length > 0) {\n onFileSelect(Array.from(files), isQuick);\n }\n }, [onFileSelect]);\n\n const handleQuickSelect = useCallback(() => {\n openSystemFilesDialog(\n CONTENT_TYPES_FOR_QUICK_UPLOAD,\n (e) => handleFileSelect(e, true),\n );\n }, [handleFileSelect]);\n\n const handleDocumentSelect = useCallback(() => {\n openSystemFilesDialog('*', (e) => handleFileSelect(e, false));\n }, [handleFileSelect]);\n\n const lang = useLang();\n\n const { canAttachMedia, canAttachPolls } = allowedAttachmentOptions;\n\n return (\n <Menu\n isOpen={isOpen}\n autoClose\n positionX=\"right\"\n positionY=\"bottom\"\n onClose={onClose}\n className=\"AttachMenu fluid\"\n onCloseAnimationEnd={onClose}\n onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}\n onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}\n noCloseOnBackdrop={!IS_TOUCH_ENV}\n >\n {/*\n ** Using ternary operator here causes some attributes from first clause\n ** transferring to the fragment content in the second clause\n */}\n {!canAttachMedia && (\n <MenuItem className=\"media-disabled\" disabled>Posting media content is not allowed in this group.</MenuItem>\n )}\n {canAttachMedia && (\n <>\n <MenuItem icon=\"photo\" onClick={handleQuickSelect}>{lang('AttachmentMenu.PhotoOrVideo')}</MenuItem>\n <MenuItem icon=\"document\" onClick={handleDocumentSelect}>Document</MenuItem>\n </>\n )}\n {canAttachPolls && (\n <MenuItem icon=\"poll\" onClick={onPollCreate}>{lang('Poll')}</MenuItem>\n )}\n </Menu>\n );\n};\n\nexport default memo(AttachMenu);\n","import React, {\n FC, memo, useEffect, useRef,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiSticker } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\n\nimport { STICKER_SIZE_PICKER } from '../../../config';\nimport { IS_TOUCH_ENV } from '../../../util/environment';\nimport buildClassName from '../../../util/buildClassName';\nimport captureEscKeyListener from '../../../util/captureEscKeyListener';\nimport { pick } from '../../../util/iteratees';\nimport { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';\nimport useShowTransition from '../../../hooks/useShowTransition';\nimport usePrevious from '../../../hooks/usePrevious';\n\nimport Loading from '../../ui/Loading';\nimport StickerButton from '../../common/StickerButton';\n\nimport './EmojiTooltip.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n onStickerSelect: (sticker: ApiSticker) => void;\n};\n\ntype StateProps = {\n stickers?: ApiSticker[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'clearStickersForEmoji'>;\n\nconst INTERSECTION_THROTTLE = 200;\n\nconst EmojiTooltip: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen,\n onStickerSelect,\n stickers,\n clearStickersForEmoji,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);\n const prevStickers = usePrevious(stickers, true);\n const displayedStickers = stickers || prevStickers;\n\n const {\n observe: observeIntersection,\n } = useIntersectionObserver({ rootRef: containerRef, throttleMs: INTERSECTION_THROTTLE });\n\n useEffect(() => (isOpen ? captureEscKeyListener(clearStickersForEmoji) : undefined), [isOpen, clearStickersForEmoji]);\n\n const handleMouseEnter = () => {\n document.body.classList.add('no-select');\n };\n\n const handleMouseLeave = () => {\n document.body.classList.remove('no-select');\n };\n\n const className = buildClassName(\n 'EmojiTooltip custom-scroll',\n transitionClassNames,\n );\n\n return (\n <div\n ref={containerRef}\n className={className}\n onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}\n onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}\n >\n {shouldRender && displayedStickers ? (\n displayedStickers.map((sticker) => (\n <StickerButton\n key={sticker.id}\n sticker={sticker}\n size={STICKER_SIZE_PICKER}\n observeIntersection={observeIntersection}\n onClick={onStickerSelect}\n clickArg={sticker}\n />\n ))\n ) : shouldRender ? (\n <Loading />\n ) : undefined}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { stickers } = global.stickers.forEmoji;\n\n return { stickers };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['clearStickersForEmoji']),\n)(EmojiTooltip));\n","import React, { FC, memo } from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiMessage } from '../../../api/types';\n\nimport { IS_TOUCH_ENV } from '../../../util/environment';\nimport { pick } from '../../../util/iteratees';\nimport { selectChatMessage, selectCurrentMessageList } from '../../../modules/selectors';\nimport useMouseInside from '../../../hooks/useMouseInside';\n\nimport Menu from '../../ui/Menu';\nimport Button from '../../ui/Button';\n\nimport './BotKeyboardMenu.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n messageId: number;\n onClose: NoneToVoidFunction;\n};\n\ntype StateProps = {\n message?: ApiMessage;\n};\n\ntype DispatchProps = Pick<GlobalActions, ('clickInlineButton')>;\n\nconst BotKeyboardMenu: FC<OwnProps & StateProps & DispatchProps> = ({\n isOpen, message, onClose, clickInlineButton,\n}) => {\n const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);\n\n if (!message || !message.keyboardButtons) {\n return undefined;\n }\n\n return (\n <Menu\n isOpen={isOpen}\n autoClose\n positionX=\"right\"\n positionY=\"bottom\"\n onClose={onClose}\n className=\"KeyboardMenu\"\n onCloseAnimationEnd={onClose}\n onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}\n onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}\n noCloseOnBackdrop={!IS_TOUCH_ENV}\n >\n <div className=\"content\">\n {message.keyboardButtons.map((row) => (\n <div className=\"row\">\n {row.map((button) => (\n <Button\n ripple\n disabled={button.type === 'NOT_SUPPORTED'}\n onClick={() => clickInlineButton({ button })}\n >\n {button.text}\n </Button>\n ))}\n </div>\n ))}\n </div>\n </Menu>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { messageId }): StateProps => {\n const { chatId } = selectCurrentMessageList(global) || {};\n if (!chatId) {\n return {};\n }\n\n return { message: selectChatMessage(global, chatId, messageId) };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'clickInlineButton',\n ]),\n)(BotKeyboardMenu));\n","import React, { FC, memo } from '../../../lib/teact/teact';\n\nimport { IS_TOUCH_ENV } from '../../../util/environment';\nimport useMouseInside from '../../../hooks/useMouseInside';\nimport useLang from '../../../hooks/useLang';\n\nimport Menu from '../../ui/Menu';\nimport MenuItem from '../../ui/MenuItem';\n\nimport './CustomSendMenu.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n onSilentSend?: NoneToVoidFunction;\n onScheduleSend?: NoneToVoidFunction;\n onClose: NoneToVoidFunction;\n onCloseAnimationEnd?: NoneToVoidFunction;\n};\n\nconst CustomSendMenu: FC<OwnProps> = ({\n isOpen, onSilentSend, onScheduleSend, onClose, onCloseAnimationEnd,\n}) => {\n const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);\n\n const lang = useLang();\n\n return (\n <Menu\n isOpen={isOpen}\n autoClose\n positionX=\"right\"\n positionY=\"bottom\"\n className=\"CustomSendMenu\"\n onClose={onClose}\n onCloseAnimationEnd={onCloseAnimationEnd}\n onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}\n onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}\n noCloseOnBackdrop={!IS_TOUCH_ENV}\n >\n {onSilentSend && <MenuItem icon=\"mute\" onClick={onSilentSend}>{lang('SendWithoutSound')}</MenuItem>}\n {onScheduleSend && <MenuItem icon=\"schedule\" onClick={onScheduleSend}>{lang('ScheduleMessage')}</MenuItem>}\n </Menu>\n );\n};\n\nexport default memo(CustomSendMenu);\n","import React, { FC, useMemo, memo } from '../../lib/teact/teact';\nimport { getGlobal, withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiMessage, ApiUser, ApiChat } from '../../api/types';\nimport { GlobalActions } from '../../global/types';\n\nimport {\n selectUser,\n selectChatMessages,\n selectChat,\n selectCurrentTextSearch,\n} from '../../modules/selectors';\nimport {\n getMessageSummaryText,\n getChatTitle,\n getUserFullName,\n isChatChannel,\n} from '../../modules/helpers';\nimport renderText from '../common/helpers/renderText';\nimport { orderBy, pick } from '../../util/iteratees';\nimport { MEMO_EMPTY_ARRAY } from '../../util/memo';\n\nimport InfiniteScroll from '../ui/InfiniteScroll';\nimport ListItem from '../ui/ListItem';\nimport LastMessageMeta from '../common/LastMessageMeta';\nimport Avatar from '../common/Avatar';\n\nimport './RightSearch.scss';\n\nexport type OwnProps = {\n chatId: number;\n threadId: number;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n messagesById?: Record<number, ApiMessage>;\n query?: string;\n totalCount?: number;\n foundIds?: number[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'searchTextMessagesLocal' | 'focusMessage'>;\n\ninterface Result {\n message: ApiMessage;\n senderUser?: ApiUser;\n senderChat?: ApiChat;\n onClick: NoneToVoidFunction;\n}\n\nconst RightSearch: FC<OwnProps & StateProps & DispatchProps> = ({\n chatId,\n threadId,\n chat,\n messagesById,\n query,\n totalCount,\n foundIds,\n searchTextMessagesLocal,\n focusMessage,\n}) => {\n const foundResults = useMemo(() => {\n if (!query || !foundIds || !foundIds.length || !messagesById) {\n return MEMO_EMPTY_ARRAY;\n }\n\n const results = foundIds.map((id) => {\n const message = messagesById[id];\n if (!message) {\n return undefined;\n }\n\n const senderUser = message.senderId ? selectUser(getGlobal(), message.senderId) : undefined;\n\n let senderChat;\n if (chat && isChatChannel(chat)) {\n senderChat = chat;\n } else if (message.forwardInfo) {\n const { isChannelPost, fromChatId } = message.forwardInfo;\n senderChat = isChannelPost && fromChatId ? selectChat(getGlobal(), fromChatId) : undefined;\n } else {\n senderChat = message.senderId ? selectChat(getGlobal(), message.senderId) : undefined;\n }\n\n return {\n message,\n senderUser,\n senderChat,\n onClick: () => focusMessage({ chatId, threadId, messageId: id }),\n };\n }).filter(Boolean) as Result[];\n\n return orderBy(results, ({ message }) => message.date, 'desc');\n }, [chatId, threadId, focusMessage, foundIds, chat, messagesById, query]);\n\n const renderSearchResult = ({\n message, senderUser, senderChat, onClick,\n }: Result) => {\n const title = senderChat ? getChatTitle(senderChat) : getUserFullName(senderUser);\n const text = getMessageSummaryText(message);\n\n return (\n <ListItem className=\"chat-item-clickable search-result-message m-0\" onClick={onClick}>\n <Avatar chat={senderChat} user={senderUser} />\n <div className=\"info\">\n <div className=\"title\">\n <h3>{title && renderText(title)}</h3>\n <LastMessageMeta message={message} />\n </div>\n <div className=\"subtitle\">\n {renderText(text, ['emoji', 'highlight'], { highlight: query })}\n </div>\n </div>\n </ListItem>\n );\n };\n\n return (\n <InfiniteScroll\n className=\"RightSearch custom-scroll\"\n items={foundResults}\n preloadBackwards={0}\n onLoadMore={searchTextMessagesLocal}\n noFastList\n >\n <p className=\"helper-text\">\n {!query ? (\n 'Search messages'\n ) : totalCount === 1 ? (\n '1 message found'\n ) : (\n `${(foundResults.length && (totalCount || foundResults.length)) || 'No'} messages found`\n )}\n </p>\n {foundResults.map(renderSearchResult)}\n </InfiniteScroll>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const messagesById = chat && selectChatMessages(global, chat.id);\n if (!chat || !messagesById) {\n return {};\n }\n\n const { query, results } = selectCurrentTextSearch(global) || {};\n const { totalCount, foundIds } = results || {};\n\n return {\n chat,\n messagesById,\n query,\n totalCount,\n foundIds,\n };\n },\n (global, actions): DispatchProps => pick(actions, ['searchTextMessagesLocal', 'focusMessage']),\n)(RightSearch));\n","import React, {\n FC, useEffect, memo, useMemo, useCallback,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiStickerSet } from '../../api/types';\nimport { GlobalActions } from '../../global/types';\nimport { ObserveFn } from '../../hooks/useIntersectionObserver';\n\nimport { STICKER_SIZE_SEARCH } from '../../config';\nimport { pick } from '../../util/iteratees';\nimport { selectShouldLoopStickers, selectStickerSet } from '../../modules/selectors';\nimport useFlag from '../../hooks/useFlag';\nimport useOnChange from '../../hooks/useOnChange';\n\nimport Button from '../ui/Button';\nimport StickerButton from '../common/StickerButton';\nimport StickerSetModal from '../common/StickerSetModal.async';\nimport Spinner from '../ui/Spinner';\n\ntype OwnProps = {\n stickerSetId: string;\n observeIntersection: ObserveFn;\n isSomeModalOpen: boolean;\n onModalToggle: (isOpen: boolean) => void;\n};\n\ntype StateProps = {\n set?: ApiStickerSet;\n shouldPlay?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadStickers' | 'toggleStickerSet'>;\n\nconst STICKERS_TO_DISPLAY = 5;\n\nconst StickerSetResult: FC<OwnProps & StateProps & DispatchProps> = ({\n stickerSetId, observeIntersection, set, shouldPlay, loadStickers, toggleStickerSet, isSomeModalOpen, onModalToggle,\n}) => {\n const isAdded = set && Boolean(set.installedDate);\n const areStickersLoaded = Boolean(set && set.stickers);\n\n const [isModalOpen, openModal, closeModal] = useFlag();\n\n useOnChange(() => {\n onModalToggle(isModalOpen);\n }, [isModalOpen, onModalToggle]);\n\n const displayedStickers = useMemo(() => {\n if (!set) {\n return [];\n }\n\n const coverStickerIds = (set.covers || []).map(({ id }) => id);\n const otherStickers = set.stickers ? set.stickers.filter(({ id }) => !coverStickerIds.includes(id)) : [];\n\n return [...set.covers || [], ...otherStickers].slice(0, STICKERS_TO_DISPLAY);\n }, [set]);\n\n useEffect(() => {\n // Featured stickers are initialized with one sticker in collection (cover of SickerSet)\n if (!areStickersLoaded && displayedStickers.length < STICKERS_TO_DISPLAY) {\n loadStickers({ stickerSetId });\n }\n }, [areStickersLoaded, displayedStickers.length, loadStickers, stickerSetId]);\n\n const handleAddClick = useCallback(() => {\n toggleStickerSet({ stickerSetId });\n }, [toggleStickerSet, stickerSetId]);\n\n if (!set) {\n return undefined;\n }\n\n const canRenderStickers = displayedStickers.length > 0;\n\n return (\n <div key={set.id} className=\"sticker-set\">\n <div className=\"sticker-set-header\">\n <div className=\"title-wrapper\">\n <h3 className=\"title\">{set.title}</h3>\n <p className=\"count\">{set.count} stickers</p>\n </div>\n <Button\n className={isAdded ? 'is-added' : undefined}\n color=\"primary\"\n size=\"tiny\"\n pill\n fluid\n onClick={handleAddClick}\n >\n {isAdded ? 'Added' : 'Add'}\n </Button>\n </div>\n <div className=\"sticker-set-main\">\n {!canRenderStickers && <Spinner />}\n {canRenderStickers && displayedStickers.map((sticker) => (\n <StickerButton\n sticker={sticker}\n size={STICKER_SIZE_SEARCH}\n observeIntersection={observeIntersection}\n noAnimate={!shouldPlay || isModalOpen || isSomeModalOpen}\n onClick={openModal}\n />\n ))}\n </div>\n {canRenderStickers && (\n <StickerSetModal\n isOpen={isModalOpen}\n fromSticker={displayedStickers[0]}\n onClose={closeModal}\n />\n )}\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { stickerSetId }): StateProps => {\n return {\n set: selectStickerSet(global, stickerSetId),\n shouldPlay: selectShouldLoopStickers(global),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadStickers', 'toggleStickerSet']),\n)(StickerSetResult));\n","import React, {\n FC, memo, useEffect, useRef, useState,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\n\nimport { pick } from '../../util/iteratees';\nimport { throttle } from '../../util/schedulers';\nimport { selectCurrentStickerSearch } from '../../modules/selectors';\nimport { useIntersectionObserver } from '../../hooks/useIntersectionObserver';\n\nimport Loading from '../ui/Loading';\nimport StickerSetResult from './StickerSetResult';\n\nimport './StickerSearch.scss';\n\ntype StateProps = {\n query?: string;\n featuredIds?: string[];\n resultIds?: string[];\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadFeaturedStickers'>;\n\nconst INTERSECTION_THROTTLE = 200;\n\nconst runThrottled = throttle((cb) => cb(), 60000, true);\n\nconst StickerSearch: FC<StateProps & DispatchProps> = ({\n query,\n featuredIds,\n resultIds,\n loadFeaturedStickers,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [isModalOpen, setIsModalOpen] = useState(false);\n\n const {\n observe: observeIntersection,\n } = useIntersectionObserver({ rootRef: containerRef, throttleMs: INTERSECTION_THROTTLE });\n\n // Due to the parent Transition, this component never gets unmounted,\n // that's why we use throttled API call on every update.\n useEffect(() => {\n runThrottled(() => {\n loadFeaturedStickers();\n });\n });\n\n function renderContent() {\n if (query === undefined) {\n return undefined;\n }\n\n if (!query && featuredIds) {\n return featuredIds.map((id) => (\n <StickerSetResult\n key={id}\n stickerSetId={id}\n observeIntersection={observeIntersection}\n isSomeModalOpen={isModalOpen}\n onModalToggle={setIsModalOpen}\n />\n ));\n }\n\n if (resultIds) {\n if (!resultIds.length) {\n return <p className=\"helper-text\">Nothing found.</p>;\n }\n\n return resultIds.map((id) => (\n <StickerSetResult\n key={id}\n stickerSetId={id}\n observeIntersection={observeIntersection}\n isSomeModalOpen={isModalOpen}\n onModalToggle={setIsModalOpen}\n />\n ));\n }\n\n return <Loading />;\n }\n\n return (\n <div ref={containerRef} className=\"StickerSearch custom-scroll\">\n {renderContent()}\n </div>\n );\n};\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const currentSearch = selectCurrentStickerSearch(global);\n const { query, resultIds } = currentSearch || {};\n const { featured } = global.stickers;\n\n return {\n query,\n featuredIds: featured.setIds,\n resultIds,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['loadFeaturedStickers']),\n)(StickerSearch));\n","import React, {\n FC, memo, useRef, useCallback,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../global/types';\nimport { ApiChat, ApiVideo } from '../../api/types';\n\nimport { IS_TOUCH_ENV } from '../../util/environment';\nimport {\n selectCurrentGifSearch,\n selectChat,\n selectIsChatWithBot,\n selectCurrentMessageList,\n} from '../../modules/selectors';\nimport { getAllowedAttachmentOptions } from '../../modules/helpers';\nimport { pick } from '../../util/iteratees';\nimport buildClassName from '../../util/buildClassName';\nimport { useIntersectionObserver } from '../../hooks/useIntersectionObserver';\nimport useLang from '../../hooks/useLang';\n\nimport InfiniteScroll from '../ui/InfiniteScroll';\nimport GifButton from '../common/GifButton';\nimport Loading from '../ui/Loading';\n\nimport './GifSearch.scss';\n\ntype StateProps = {\n query?: string;\n results?: ApiVideo[];\n chat?: ApiChat;\n isChatWithBot?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'searchMoreGifs' | 'sendMessage' | 'setGifSearchQuery'>;\n\nconst PRELOAD_BACKWARDS = 96; // GIF Search bot results are multiplied by 24\nconst INTERSECTION_DEBOUNCE = 300;\n\nconst GifSearch: FC<StateProps & DispatchProps> = ({\n query,\n results,\n chat,\n isChatWithBot,\n searchMoreGifs,\n sendMessage,\n setGifSearchQuery,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n\n const {\n observe: observeIntersection,\n } = useIntersectionObserver({ rootRef: containerRef, debounceMs: INTERSECTION_DEBOUNCE });\n\n const { canSendGifs } = getAllowedAttachmentOptions(chat, isChatWithBot);\n\n const handleGifClick = useCallback((gif: ApiVideo) => {\n if (canSendGifs) {\n sendMessage({ gif });\n }\n\n if (IS_TOUCH_ENV) {\n setGifSearchQuery({ query: undefined });\n }\n }, [canSendGifs, sendMessage, setGifSearchQuery]);\n\n const lang = useLang();\n\n function renderContent() {\n if (query === undefined) {\n return undefined;\n }\n\n if (!results) {\n return (\n <Loading />\n );\n }\n\n if (!results.length) {\n return (\n <p className=\"helper-text\">{lang('NoGIFsFound')}</p>\n );\n }\n\n return results.map((gif) => (\n <GifButton\n key={gif.id}\n gif={gif}\n observeIntersection={observeIntersection}\n onClick={handleGifClick}\n />\n ));\n }\n\n const hasResults = Boolean(query !== undefined && results && results.length);\n\n return (\n <div className=\"GifSearch\">\n <InfiniteScroll\n ref={containerRef}\n className={buildClassName('gif-container custom-scroll', hasResults && 'grid')}\n items={results}\n itemSelector=\".GifButton\"\n preloadBackwards={PRELOAD_BACKWARDS}\n noFastList\n onLoadMore={searchMoreGifs}\n >\n {renderContent()}\n </InfiniteScroll>\n\n </div>\n );\n};\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const currentSearch = selectCurrentGifSearch(global);\n const { query, results } = currentSearch || {};\n const { chatId } = selectCurrentMessageList(global) || {};\n const chat = chatId ? selectChat(global, chatId) : undefined;\n const isChatWithBot = chat ? selectIsChatWithBot(global, chat) : undefined;\n\n return {\n query,\n results,\n chat,\n isChatWithBot,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['searchMoreGifs', 'sendMessage', 'setGifSearchQuery']),\n)(GifSearch));\n","import React, {\n FC, memo, useState, useEffect, useRef,\n} from '../../lib/teact/teact';\n\nimport buildClassName from '../../util/buildClassName';\n\nimport Loading from '../ui/Loading';\n\nimport './Statistics.scss';\n\ntype ILovelyChart = { create: Function };\nlet lovelyChartPromise: Promise<ILovelyChart>;\nlet LovelyChart: ILovelyChart;\n\nasync function ensureLovelyChart() {\n if (!lovelyChartPromise) {\n lovelyChartPromise = import('../../lib/lovely-chart/LovelyChart') as Promise<ILovelyChart>;\n LovelyChart = await lovelyChartPromise;\n }\n\n return lovelyChartPromise;\n}\n\nconst Statistics: FC = () => {\n // eslint-disable-next-line no-null/no-null\n const containerRef = useRef<HTMLDivElement>(null);\n const [isReady, setIsReady] = useState(false);\n const [loadedChartsCount, setLoadedChartsCount] = useState(0);\n\n useEffect(() => {\n (async () => {\n await ensureLovelyChart();\n\n if (!isReady) {\n setIsReady(true);\n return;\n }\n\n const growth = await fetchJson('./chartDummyData/growth.json');\n LovelyChart.create(containerRef.current!.children[0], growth);\n setLoadedChartsCount(1);\n\n const notifications = await fetchJson('./chartDummyData/notifications.json');\n notifications.onZoom = (timestamp: number) => fetchDayData('chartDummyData/notifications_zoom', timestamp);\n LovelyChart.create(containerRef.current!.children[1], notifications);\n setLoadedChartsCount(2);\n\n const interactions = await fetchJson('./chartDummyData/interactions.json');\n LovelyChart.create(containerRef.current!.children[2], interactions);\n setLoadedChartsCount(3);\n\n const views = await fetchJson('./chartDummyData/views.json');\n views.onZoom = (timestamp: number) => fetchDayData('chartDummyData/views_zoom', timestamp);\n LovelyChart.create(containerRef.current!.children[3], views);\n setLoadedChartsCount(4);\n\n const languages = await fetchJson('./chartDummyData/languages.json');\n LovelyChart.create(containerRef.current!.children[4], languages);\n setLoadedChartsCount(5);\n })();\n }, [isReady]);\n\n return (\n <div className={buildClassName('Statistics custom-scroll', isReady && 'ready')} ref={containerRef}>\n {!isReady ? (\n <Loading />\n ) : (\n <>\n <div className={buildClassName('chat-container', loadedChartsCount < 1 && 'hidden')} />\n <div className={buildClassName('chat-container', loadedChartsCount < 2 && 'hidden')} />\n <div className={buildClassName('chat-container', loadedChartsCount < 3 && 'hidden')} />\n <div className={buildClassName('chat-container', loadedChartsCount < 4 && 'hidden')} />\n <div className={buildClassName('chat-container', loadedChartsCount < 5 && 'hidden')} />\n </>\n )}\n </div>\n );\n};\n\nfunction fetchJson(path: string) {\n return fetch(path).then((response) => response.json());\n}\n\nfunction fetchDayData(dataSource: string, timestamp: number) {\n const date = new Date(timestamp);\n const month = date.getMonth() + 1;\n const day = date.getDate();\n const path = `${date.getFullYear()}-${month < 10 ? '0' : ''}${month}/${day < 10 ? '0' : ''}${day}`;\n\n return fetchJson(`${dataSource}/${path}.json`);\n}\n\nexport default memo(Statistics);\n","import React, {\n FC, useCallback, useState, memo, useEffect,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport {\n ApiChat,\n ApiMessage,\n ApiPollAnswer,\n ApiPollResult,\n} from '../../api/types';\nimport { GlobalActions } from '../../global/types';\nimport { pick } from '../../util/iteratees';\nimport usePrevious from '../../hooks/usePrevious';\n\nimport ShowMoreButton from '../ui/ShowMoreButton';\nimport Loading from '../ui/Loading';\nimport ListItem from '../ui/ListItem';\nimport PrivateChatInfo from '../common/PrivateChatInfo';\n\nimport './PollAnswerResults.scss';\n\ntype OwnProps = {\n chat: ApiChat;\n message: ApiMessage;\n answer: ApiPollAnswer;\n answerVote: ApiPollResult;\n totalVoters: number;\n};\n\ntype StateProps = {\n voters?: number[];\n offset: string;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadPollOptionResults' | 'openChat' | 'closePollResults'>;\n\nconst INITIAL_LIMIT = 4;\nconst VIEW_MORE_LIMIT = 50;\n\nconst PollAnswerResults: FC<OwnProps & StateProps & DispatchProps> = ({\n chat,\n message,\n answer,\n answerVote,\n totalVoters,\n voters,\n offset,\n loadPollOptionResults,\n openChat,\n closePollResults,\n}) => {\n const prevVotersCount = usePrevious<number>(answerVote.votersCount);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const areVotersLoaded = Boolean(voters);\n const { option, text } = answer;\n\n useEffect(() => {\n // For update when new votes arrive or when the user takes back his vote\n if (!areVotersLoaded || prevVotersCount !== answerVote.votersCount) {\n loadPollOptionResults({\n chat, messageId: message.id, option, offset, limit: INITIAL_LIMIT, shouldResetVoters: true,\n });\n }\n // eslint-disable-next-line\n }, [answerVote.votersCount, areVotersLoaded]);\n\n const handleViewMoreClick = useCallback(() => {\n setIsLoading(true);\n loadPollOptionResults({\n chat, messageId: message.id, option, offset, limit: VIEW_MORE_LIMIT,\n });\n }, [chat, loadPollOptionResults, message.id, offset, option]);\n\n useEffect(() => {\n setIsLoading(false);\n }, [voters]);\n\n const handleMemberClick = useCallback((id: number) => {\n openChat({ id });\n closePollResults();\n }, [closePollResults, openChat]);\n\n function renderViewMoreButton() {\n const leftVotersCount = answerVote.votersCount - voters!.length;\n\n return answerVote.votersCount > INITIAL_LIMIT && leftVotersCount > 0 && (\n <ShowMoreButton\n count={leftVotersCount}\n itemName=\"voter\"\n isLoading={isLoading}\n onClick={handleViewMoreClick}\n />\n );\n }\n\n return (\n <div className=\"PollAnswerResults\">\n <div className=\"poll-voters\">\n {voters\n ? voters.map((id) => (\n <ListItem\n key={id}\n className=\"chat-item-clickable\"\n onClick={() => handleMemberClick(id)}\n >\n <PrivateChatInfo\n avatarSize=\"tiny\"\n userId={id}\n forceShowSelf\n noStatusOrTyping\n />\n </ListItem>\n ))\n : <Loading />}\n {voters && renderViewMoreButton()}\n </div>\n <div className=\"answer-head\">\n <span className=\"answer-title\">{text}</span>\n <span className=\"answer-percent\">{getPercentage(answerVote.votersCount, totalVoters)}%</span>\n </div>\n </div>\n );\n};\n\nfunction getPercentage(value: number, total: number) {\n return total > 0 ? ((value / total) * 100).toFixed() : 0;\n}\n\nexport default memo(withGlobal<OwnProps>(\n (global, { answer }: OwnProps): StateProps => {\n const { voters, offsets } = global.pollResults;\n\n return {\n voters: voters && voters[answer.option],\n offset: (offsets && offsets[answer.option]) || '',\n };\n },\n (global, actions): DispatchProps => pick(actions, ['loadPollOptionResults', 'openChat', 'closePollResults']),\n)(PollAnswerResults));\n","import React, { FC, memo } from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { ApiMessage, ApiChat } from '../../api/types';\nimport { selectChat, selectChatMessage } from '../../modules/selectors';\nimport { buildCollectionByKey } from '../../util/iteratees';\nimport { getMessagePoll } from '../../modules/helpers';\n\nimport PollAnswerResults from './PollAnswerResults';\nimport Loading from '../ui/Loading';\n\nimport './PollResults.scss';\n\ntype StateProps = {\n chat?: ApiChat;\n message?: ApiMessage;\n lastSyncTime?: number;\n};\n\nconst PollResults: FC<StateProps> = ({\n chat,\n message,\n lastSyncTime,\n}) => {\n if (!message || !chat) {\n return <Loading />;\n }\n\n const { summary, results } = getMessagePoll(message)!;\n if (!results.results) {\n return undefined;\n }\n\n const resultsByOption = buildCollectionByKey(results.results, 'option');\n\n return (\n <div className=\"PollResults\">\n <h3 className=\"poll-question\">{summary.question}</h3>\n <div className=\"poll-results-list custom-scroll\">\n {lastSyncTime && summary.answers.map((answer) => (\n <PollAnswerResults\n key={`${message.id}-${answer.option}`}\n chat={chat}\n message={message}\n answer={answer}\n answerVote={resultsByOption[answer.option]}\n totalVoters={results.totalVoters!}\n />\n ))}\n {!lastSyncTime && <Loading />}\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal(\n (global): StateProps => {\n const {\n pollResults: { chatId, messageId },\n lastSyncTime,\n } = global;\n\n if (!chatId || !messageId) {\n return {};\n }\n\n const chat = selectChat(global, chatId);\n const message = selectChatMessage(global, chatId, messageId);\n\n return {\n chat,\n message,\n lastSyncTime,\n };\n },\n)(PollResults));\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiChat, ApiUser } from '../../../api/types';\nimport { ManagementProgress } from '../../../types';\n\nimport { pick } from '../../../util/iteratees';\nimport { selectChat, selectUser } from '../../../modules/selectors';\nimport useFlag from '../../../hooks/useFlag';\nimport useLang from '../../../hooks/useLang';\n\nimport InputText from '../../ui/InputText';\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\nimport './Management.scss';\n\ntype OwnProps = {\n userId: number;\n};\n\ntype StateProps = {\n user?: ApiUser;\n chat: ApiChat;\n progress?: ManagementProgress;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'updateContact' | 'deleteUser' | 'deleteHistory' | 'closeManagement' | 'openChat'\n)>;\n\nconst ERROR_FIRST_NAME_MISSING = 'Please provide first name';\n\nconst ManageUser: FC<OwnProps & StateProps & DispatchProps> = ({\n userId,\n user,\n chat,\n progress,\n updateContact,\n deleteUser,\n deleteHistory,\n closeManagement,\n openChat,\n}) => {\n const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();\n const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);\n const [error, setError] = useState<string | undefined>();\n const lang = useLang();\n\n const currentFirstName = user ? (user.firstName || '') : '';\n const currentLastName = user ? (user.lastName || '') : '';\n const currentIsMuted = chat ? chat.isMuted : undefined;\n\n const [firstName, setFirstName] = useState(currentFirstName);\n const [lastName, setLastName] = useState(currentLastName);\n const [isNotificationsEnabled, setIsNotificationsEnabled] = useState(!currentIsMuted);\n\n useEffect(() => {\n setIsNotificationsEnabled(!currentIsMuted);\n }, [currentIsMuted]);\n\n useEffect(() => {\n setIsProfileFieldsTouched(false);\n closeDeleteDialog();\n }, [closeDeleteDialog, userId]);\n\n useEffect(() => {\n setFirstName(currentFirstName);\n setLastName(currentLastName);\n }, [currentFirstName, currentLastName, user]);\n\n useEffect(() => {\n if (progress === ManagementProgress.Complete) {\n setIsProfileFieldsTouched(false);\n setError(undefined);\n closeDeleteDialog();\n }\n }, [closeDeleteDialog, progress]);\n\n const handleFirstNameChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setFirstName(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleLastNameChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setLastName(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleNotificationChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setIsNotificationsEnabled(e.target.checked);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleProfileSave = useCallback(() => {\n const trimmedFirstName = firstName.trim();\n const trimmedLastName = lastName.trim();\n\n if (!trimmedFirstName.length) {\n setError(ERROR_FIRST_NAME_MISSING);\n }\n\n updateContact({\n userId,\n isMuted: !isNotificationsEnabled,\n firstName: trimmedFirstName,\n lastName: trimmedLastName,\n });\n }, [firstName, lastName, updateContact, userId, isNotificationsEnabled]);\n\n const handleDeleteContact = useCallback(() => {\n if (chat.lastMessage) {\n deleteHistory({\n chatId: chat.id,\n maxId: chat.lastMessage!.id,\n shouldDeleteForAll: false,\n });\n }\n deleteUser({ userId });\n closeDeleteDialog();\n closeManagement();\n openChat({ id: undefined });\n }, [chat.id, chat.lastMessage, closeDeleteDialog, closeManagement, deleteHistory, deleteUser, openChat, userId]);\n\n if (!user) {\n return undefined;\n }\n\n const isLoading = progress === ManagementProgress.InProgress;\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <PrivateChatInfo\n userId={user.id}\n avatarSize=\"jumbo\"\n status=\"original name\"\n withMediaViewer\n withFullInfo\n />\n <InputText\n id=\"user-first-name\"\n label={lang('UserInfo.FirstNamePlaceholder')}\n onChange={handleFirstNameChange}\n value={firstName}\n error={error === ERROR_FIRST_NAME_MISSING ? error : undefined}\n />\n <InputText\n id=\"user-last-name\"\n label={lang('UserInfo.LastNamePlaceholder')}\n onChange={handleLastNameChange}\n value={lastName}\n />\n <div className=\"ListItem no-selection narrow\">\n <Checkbox\n checked={isNotificationsEnabled}\n label={lang('Notifications')}\n subLabel={lang(isNotificationsEnabled\n ? 'UserInfo.NotificationsEnabled'\n : 'UserInfo.NotificationsDisabled')}\n onChange={handleNotificationChange}\n />\n </div>\n </div>\n <div className=\"section\">\n <ListItem icon=\"delete\" ripple destructive onClick={openDeleteDialog}>\n {lang('DeleteContact')}\n </ListItem>\n </div>\n </div>\n <FloatingActionButton\n isShown={isProfileFieldsTouched}\n onClick={handleProfileSave}\n disabled={isLoading}\n ariaLabel={lang('Save')}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n <ConfirmDialog\n isOpen={isDeleteDialogOpen}\n onClose={closeDeleteDialog}\n text={lang('AreYouSureDeleteContact')}\n confirmLabel={lang('DeleteContact')}\n confirmHandler={handleDeleteContact}\n confirmIsDestructive\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { userId }): StateProps => {\n const user = selectUser(global, userId);\n const chat = selectChat(global, userId)!;\n const { progress } = global.management;\n\n return { user, chat, progress };\n },\n (global, actions): DispatchProps => pick(actions, [\n 'updateContact', 'deleteUser', 'closeManagement', 'openChat', 'deleteHistory',\n ]),\n)(ManageUser));\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ManagementScreens, ManagementProgress } from '../../../types';\nimport { ApiChat, ApiChatBannedRights, ApiMediaFormat } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\n\nimport { getChatAvatarHash, getHasAdminRight, isChatBasicGroup } from '../../../modules/helpers';\nimport useMedia from '../../../hooks/useMedia';\nimport useLang from '../../../hooks/useLang';\nimport useFlag from '../../../hooks/useFlag';\nimport { selectChat } from '../../../modules/selectors';\nimport { formatInteger } from '../../../util/textFormat';\nimport { pick } from '../../../util/iteratees';\nimport renderText from '../../common/helpers/renderText';\n\nimport AvatarEditable from '../../ui/AvatarEditable';\nimport InputText from '../../ui/InputText';\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport Spinner from '../../ui/Spinner';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\nimport './Management.scss';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n};\n\ntype StateProps = {\n chat: ApiChat;\n progress?: ManagementProgress;\n isBasicGroup: boolean;\n hasLinkedChannel: boolean;\n canChangeInfo?: boolean;\n canBanUsers?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'togglePreHistoryHidden' | 'updateChat' | 'closeManagement' |\n 'deleteHistory' | 'leaveChannel' | 'deleteChannel' | 'openChat'\n)>;\n\nconst GROUP_TITLE_EMPTY = 'Group title can\\'t be empty';\n\n// Some checkboxes control multiple rights, and some rights are not controlled from Permissions screen,\n// so we need to define the amount manually\nconst TOTAL_PERMISSIONS_COUNT = 8;\n\nconst ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({\n chatId,\n chat,\n progress,\n isBasicGroup,\n hasLinkedChannel,\n canChangeInfo,\n canBanUsers,\n onScreenSelect,\n togglePreHistoryHidden,\n updateChat,\n deleteHistory,\n leaveChannel,\n deleteChannel,\n closeManagement,\n openChat,\n}) => {\n const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();\n const currentTitle = chat.title;\n const currentAbout = chat.fullInfo ? (chat.fullInfo.about || '') : '';\n\n const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);\n const [title, setTitle] = useState(currentTitle);\n const [about, setAbout] = useState(currentAbout);\n const [photo, setPhoto] = useState<File | undefined>();\n const [error, setError] = useState<string | undefined>();\n const imageHash = getChatAvatarHash(chat);\n const currentAvatarBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl);\n const lang = useLang();\n\n useEffect(() => {\n if (progress === ManagementProgress.Complete) {\n setIsProfileFieldsTouched(false);\n setError(undefined);\n }\n }, [progress]);\n\n const handleClickEditType = useCallback(() => {\n onScreenSelect(ManagementScreens.ChatPrivacyType);\n }, [onScreenSelect]);\n\n const handleClickDiscussion = useCallback(() => {\n onScreenSelect(ManagementScreens.Discussion);\n }, [onScreenSelect]);\n\n const handleClickPermissions = useCallback(() => {\n onScreenSelect(ManagementScreens.GroupPermissions);\n }, [onScreenSelect]);\n\n const handleClickAdministrators = useCallback(() => {\n onScreenSelect(ManagementScreens.ChatAdministrators);\n }, [onScreenSelect]);\n\n const handleSetPhoto = useCallback((file: File) => {\n setPhoto(file);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleTitleChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setTitle(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleAboutChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setAbout(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleUpdateGroup = useCallback(() => {\n const trimmedTitle = title.trim();\n const trimmedAbout = about.trim();\n\n if (!trimmedTitle.length) {\n setError(GROUP_TITLE_EMPTY);\n return;\n }\n\n updateChat({\n chatId,\n title: trimmedTitle,\n about: trimmedAbout,\n photo,\n });\n }, [about, chatId, photo, title, updateChat]);\n\n const handleClickMembers = useCallback(() => {\n onScreenSelect(ManagementScreens.GroupMembers);\n }, [onScreenSelect]);\n\n const handleTogglePreHistory = useCallback(() => {\n if (!chat.fullInfo) {\n return;\n }\n\n const { isPreHistoryHidden } = chat.fullInfo;\n\n togglePreHistoryHidden({ chatId: chat.id, isEnabled: !isPreHistoryHidden });\n }, [chat, togglePreHistoryHidden]);\n\n const enabledPermissionsCount = useMemo(() => {\n if (!chat.defaultBannedRights) {\n return 0;\n }\n\n let totalCount = [\n 'sendMessages',\n 'sendMedia',\n 'embedLinks',\n 'sendPolls',\n 'changeInfo',\n 'inviteUsers',\n 'pinMessages',\n ].filter(\n (key) => !chat.defaultBannedRights![key as keyof ApiChatBannedRights],\n ).length;\n\n const { sendStickers, sendGifs } = chat.defaultBannedRights;\n\n // These two rights are controlled with a single checkbox\n if (!sendStickers && !sendGifs) {\n totalCount += 1;\n }\n\n return totalCount;\n }, [chat]);\n\n const adminsCount = (chat.fullInfo && chat.fullInfo.adminMembers && chat.fullInfo.adminMembers.length) || 0;\n\n const handleDeleteGroup = useCallback(() => {\n if (isBasicGroup) {\n deleteHistory({ chatId: chat.id, maxId: chat.lastMessage!.id, shouldDeleteForAll: false });\n } else if (!chat.isCreator) {\n leaveChannel({ chatId: chat.id });\n } else {\n deleteChannel({ chatId: chat.id });\n }\n closeDeleteDialog();\n closeManagement();\n openChat({ id: undefined });\n }, [\n isBasicGroup, chat.isCreator, chat.id, chat.lastMessage,\n closeDeleteDialog, closeManagement, deleteHistory, leaveChannel, deleteChannel, openChat,\n ]);\n\n if (chat.isRestricted) {\n return undefined;\n }\n\n const isLoading = progress === ManagementProgress.InProgress;\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <AvatarEditable\n currentAvatarBlobUrl={currentAvatarBlobUrl}\n onChange={handleSetPhoto}\n disabled={!canChangeInfo}\n />\n <InputText\n id=\"group-title\"\n label={lang('GroupName')}\n onChange={handleTitleChange}\n value={title}\n error={error === GROUP_TITLE_EMPTY ? error : undefined}\n disabled={!canChangeInfo}\n />\n <InputText\n id=\"group-about\"\n className=\"mb-2\"\n label={lang('DescriptionPlaceholder')}\n onChange={handleAboutChange}\n value={about}\n disabled={!canChangeInfo}\n />\n {chat.isCreator && (\n <ListItem icon=\"lock\" ripple onClick={handleClickEditType}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('GroupType')}</span>\n <span className=\"subtitle\">{chat.username ? lang('TypePublic') : lang('TypePrivate')}</span>\n </div>\n </ListItem>\n )}\n {hasLinkedChannel && (\n <ListItem icon=\"message\" ripple onClick={handleClickDiscussion}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('LinkedChannel')}</span>\n <span className=\"subtitle\">{lang('DiscussionUnlink')}</span>\n </div>\n </ListItem>\n )}\n <ListItem icon=\"permissions\" ripple onClick={handleClickPermissions} disabled={!canBanUsers}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelPermissions')}</span>\n <span className=\"subtitle\">{enabledPermissionsCount}/{TOTAL_PERMISSIONS_COUNT}</span>\n </div>\n </ListItem>\n <ListItem icon=\"admin\" ripple onClick={handleClickAdministrators}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelAdministrators')}</span>\n <span className=\"subtitle\">{formatInteger(adminsCount)}</span>\n </div>\n </ListItem>\n </div>\n <div className=\"section\">\n <ListItem icon=\"group\" ripple onClick={handleClickMembers}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('GroupMembers')}</span>\n <span className=\"subtitle\">{formatInteger(chat.membersCount!)}</span>\n </div>\n </ListItem>\n\n {chat.fullInfo && (\n <div className=\"ListItem narrow no-selection\">\n <Checkbox\n checked={!chat.fullInfo.isPreHistoryHidden}\n label={lang('ChatHistory')}\n onChange={handleTogglePreHistory}\n disabled={!canBanUsers}\n />\n </div>\n )}\n </div>\n <div className=\"section\">\n <ListItem icon=\"delete\" ripple destructive onClick={openDeleteDialog}>\n {lang('DeleteMega')}\n </ListItem>\n </div>\n </div>\n <FloatingActionButton\n isShown={isProfileFieldsTouched}\n onClick={handleUpdateGroup}\n disabled={isLoading}\n ariaLabel={lang('Save')}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n <ConfirmDialog\n isOpen={isDeleteDialogOpen}\n onClose={closeDeleteDialog}\n textParts={renderText(\n isBasicGroup || !chat.isCreator\n ? lang('AreYouSureDeleteAndExit')\n : lang('AreYouSureDeleteThisChatWithGroup', chat.title),\n ['br', 'simple_markdown'],\n )}\n confirmLabel={isBasicGroup || !chat.isCreator ? lang('DeleteMega') : lang('DeleteGroupForAll')}\n confirmHandler={handleDeleteGroup}\n confirmIsDestructive\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const { progress } = global.management;\n const hasLinkedChannel = Boolean(chat.fullInfo && chat.fullInfo.linkedChatId);\n\n return {\n chat,\n progress,\n isBasicGroup: isChatBasicGroup(chat),\n hasLinkedChannel,\n canChangeInfo: getHasAdminRight(chat, 'changeInfo'),\n canBanUsers: getHasAdminRight(chat, 'banUsers'),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'togglePreHistoryHidden', 'updateChat', 'closeManagement',\n 'deleteHistory', 'leaveChannel', 'deleteChannel', 'openChat',\n ]),\n)(ManageGroup));\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ManagementScreens } from '../../../types';\nimport { ApiChat, ApiChatBannedRights, ApiChatMember } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\n\nimport useLang from '../../../hooks/useLang';\nimport { selectChat } from '../../../modules/selectors';\nimport { pick } from '../../../util/iteratees';\n\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n onChatMemberSelect: (memberId: number, isPromotedByCurrentUser?: boolean) => void;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n currentUserId?: number;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'updateChatDefaultBannedRights'>;\n\nconst FLOATING_BUTTON_ANIMATION_TIMEOUT_MS = 250;\n\nfunction getLangKeyForBannedRightKey(key: string) {\n switch (key) {\n case 'sendMessages':\n return 'UserRestrictionsNoSend';\n case 'sendMedia':\n return 'UserRestrictionsNoSendMedia';\n case 'sendStickers':\n return 'UserRestrictionsNoSendStickers';\n case 'embedLinks':\n return 'UserRestrictionsNoEmbedLinks';\n case 'sendPolls':\n return 'UserRestrictionsNoSendPolls';\n case 'changeInfo':\n return 'UserRestrictionsNoChangeInfo';\n case 'inviteUsers':\n return 'UserRestrictionsInviteUsers';\n case 'pinMessages':\n return 'UserRestrictionsPinMessages';\n default:\n return undefined;\n }\n}\n\nconst ManageGroupPermissions: FC<OwnProps & StateProps & DispatchProps> = ({\n onScreenSelect,\n onChatMemberSelect,\n chat,\n currentUserId,\n updateChatDefaultBannedRights,\n}) => {\n const [permissions, setPermissions] = useState<ApiChatBannedRights>({});\n const [havePermissionChanged, setHavePermissionChanged] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const lang = useLang();\n\n const handleRemovedUsersClick = useCallback(() => {\n onScreenSelect(ManagementScreens.GroupRemovedUsers);\n }, [onScreenSelect]);\n\n const handleAddExceptionClick = useCallback(() => {\n onScreenSelect(ManagementScreens.GroupUserPermissionsCreate);\n }, [onScreenSelect]);\n\n const handleExceptionMemberClick = useCallback((member: ApiChatMember) => {\n onChatMemberSelect(member.userId, member.promotedByUserId === currentUserId);\n onScreenSelect(ManagementScreens.GroupUserPermissions);\n }, [currentUserId, onChatMemberSelect, onScreenSelect]);\n\n useEffect(() => {\n setPermissions((chat && chat.defaultBannedRights) || {});\n setHavePermissionChanged(false);\n setTimeout(() => {\n setIsLoading(false);\n }, FLOATING_BUTTON_ANIMATION_TIMEOUT_MS);\n }, [chat]);\n\n const handlePermissionChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { name } = e.target;\n\n function getUpdatedPermissionValue(value: true | undefined) {\n return value ? undefined : true;\n }\n\n setPermissions((p) => ({\n ...p,\n [name]: getUpdatedPermissionValue(p[name as keyof ApiChatBannedRights]),\n ...(name === 'sendStickers' && {\n sendGifs: getUpdatedPermissionValue(p[name]),\n }),\n }));\n setHavePermissionChanged(true);\n }, []);\n\n const handleSavePermissions = useCallback(() => {\n if (!chat) {\n return;\n }\n\n setIsLoading(true);\n updateChatDefaultBannedRights({ chatId: chat.id, bannedRights: permissions });\n }, [chat, permissions, updateChatDefaultBannedRights]);\n\n const removedUsersCount = useMemo(() => {\n if (!chat || !chat.fullInfo || !chat.fullInfo.kickedMembers) {\n return 0;\n }\n\n return chat.fullInfo.kickedMembers.length;\n }, [chat]);\n\n const exceptionMembers = useMemo(() => {\n if (!chat || !chat.fullInfo || !chat.fullInfo.members) {\n return [];\n }\n\n return chat.fullInfo.members.filter(({ bannedRights }) => !!bannedRights);\n }, [chat]);\n\n const getMemberExceptions = useCallback((member: ApiChatMember) => {\n const { bannedRights } = member;\n if (!bannedRights || !chat) {\n return undefined;\n }\n\n const { defaultBannedRights } = chat;\n\n return Object.keys(bannedRights).reduce((result, key) => {\n if (\n !bannedRights[key as keyof ApiChatBannedRights]\n || (defaultBannedRights && defaultBannedRights[key as keyof ApiChatBannedRights])\n || key === 'sendInline' || key === 'viewMessages' || key === 'sendGames'\n ) {\n return result;\n }\n\n const langKey = getLangKeyForBannedRightKey(key);\n\n if (!langKey) {\n return result;\n }\n\n const translatedString = lang(langKey);\n\n return `${result}${!result.length ? translatedString : `, ${translatedString}`}`;\n }, '');\n }, [chat, lang]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <h3 className=\"section-heading\">{lang('ChannelPermissionsHeader')}</h3>\n\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendMessages\"\n checked={!permissions.sendMessages}\n label={lang('UserRestrictionsSend')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendMedia\"\n checked={!permissions.sendMedia}\n label={lang('UserRestrictionsSendMedia')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendStickers\"\n checked={!permissions.sendStickers && !permissions.sendGifs}\n label={lang('UserRestrictionsSendStickers')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendPolls\"\n checked={!permissions.sendPolls}\n label={lang('UserRestrictionsSendPolls')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"embedLinks\"\n checked={!permissions.embedLinks}\n label={lang('UserRestrictionsEmbedLinks')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"inviteUsers\"\n checked={!permissions.inviteUsers}\n label={lang('UserRestrictionsInviteUsers')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"pinMessages\"\n checked={!permissions.pinMessages}\n label={lang('UserRestrictionsPinMessages')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!permissions.changeInfo}\n label={lang('UserRestrictionsChangeInfo')}\n blocking\n onChange={handlePermissionChange}\n />\n </div>\n </div>\n\n <div className=\"section\">\n <ListItem icon=\"delete-user\" ripple narrow onClick={handleRemovedUsersClick}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelBlockedUsers')}</span>\n <span className=\"subtitle\">{removedUsersCount}</span>\n </div>\n </ListItem>\n </div>\n\n <div className=\"section\">\n <h3 className=\"section-heading\">{lang('PrivacyExceptions')}</h3>\n\n <ListItem\n icon=\"add-user\"\n ripple\n onClick={handleAddExceptionClick}\n >\n {lang('ChannelAddException')}\n </ListItem>\n\n {exceptionMembers.map((member) => (\n <ListItem\n key={member.userId}\n className=\"chat-item-clickable exceptions-member\"\n ripple\n onClick={() => handleExceptionMemberClick(member)}\n >\n <PrivateChatInfo\n userId={member.userId}\n status={getMemberExceptions(member)}\n />\n </ListItem>\n ))}\n </div>\n </div>\n\n <FloatingActionButton\n isShown={havePermissionChanged}\n onClick={handleSavePermissions}\n ariaLabel={lang('Save')}\n disabled={isLoading}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n\n return { chat, currentUserId: global.currentUserId };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['updateChatDefaultBannedRights']),\n)(ManageGroupPermissions));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiChatMember, ApiUser } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\n\nimport { selectChat } from '../../../modules/selectors';\nimport { getUserFullName } from '../../../modules/helpers';\nimport { pick } from '../../../util/iteratees';\nimport useLang from '../../../hooks/useLang';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport ListItem from '../../ui/ListItem';\n\ntype OwnProps = {\n chatId: number;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n usersById: Record<number, ApiUser>;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'updateChatMemberBannedRights'>;\n\nconst ManageGroupRemovedUsers: FC<OwnProps & StateProps & DispatchProps> = ({\n chat,\n usersById,\n updateChatMemberBannedRights,\n}) => {\n const lang = useLang();\n\n const removedMembers = useMemo(() => {\n if (!chat || !chat.fullInfo || !chat.fullInfo.kickedMembers) {\n return [];\n }\n\n return chat.fullInfo.kickedMembers;\n }, [chat]);\n\n const getRemovedBy = useCallback((member: ApiChatMember) => {\n if (!member.kickedByUserId) {\n return undefined;\n }\n\n const kickedByUser = usersById[member.kickedByUserId];\n if (!kickedByUser) {\n return undefined;\n }\n\n return lang('UserRemovedBy', getUserFullName(kickedByUser));\n }, [lang, usersById]);\n\n const getContextActions = useCallback((member: ApiChatMember) => {\n if (!chat) {\n return undefined;\n }\n\n return [{\n title: lang('Unblock'),\n icon: 'delete',\n destructive: true,\n handler: () => updateChatMemberBannedRights({\n chatId: chat.id,\n userId: member.userId,\n bannedRights: {},\n }),\n }];\n }, [lang, chat, updateChatMemberBannedRights]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <p className=\"text-muted\">{lang('NoBlockedGroup2')}</p>\n\n {removedMembers.map((member) => (\n <ListItem\n key={member.userId}\n className=\"chat-item-clickable\"\n ripple\n contextActions={getContextActions(member)}\n >\n <PrivateChatInfo\n userId={member.userId}\n status={getRemovedBy(member)}\n />\n </ListItem>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const { byId: usersById } = global.users;\n\n return { chat, usersById };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['updateChatMemberBannedRights']),\n)(ManageGroupRemovedUsers));\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ManagementScreens, ManagementProgress } from '../../../types';\nimport { ApiChat, ApiMediaFormat } from '../../../api/types';\n\nimport { pick } from '../../../util/iteratees';\nimport { getChatAvatarHash, getHasAdminRight } from '../../../modules/helpers';\nimport useMedia from '../../../hooks/useMedia';\nimport useLang from '../../../hooks/useLang';\nimport { selectChat } from '../../../modules/selectors';\n\nimport AvatarEditable from '../../ui/AvatarEditable';\nimport InputText from '../../ui/InputText';\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport Spinner from '../../ui/Spinner';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\nimport useFlag from '../../../hooks/useFlag';\n\nimport './Management.scss';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n};\n\ntype StateProps = {\n chat: ApiChat;\n progress?: ManagementProgress;\n isSignaturesShown: boolean;\n canChangeInfo?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'toggleSignatures' | 'updateChat' | 'closeManagement' | 'leaveChannel' | 'deleteChannel' | 'openChat'\n)>;\n\nconst CHANNEL_TITLE_EMPTY = 'Channel title can\\'t be empty';\n\nconst ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({\n chatId,\n chat,\n progress,\n isSignaturesShown,\n canChangeInfo,\n onScreenSelect,\n updateChat,\n toggleSignatures,\n closeManagement,\n leaveChannel,\n deleteChannel,\n openChat,\n}) => {\n const currentTitle = chat ? (chat.title || '') : '';\n const currentAbout = chat && chat.fullInfo ? (chat.fullInfo.about || '') : '';\n const hasLinkedChat = chat && chat.fullInfo && chat.fullInfo.linkedChatId;\n\n const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();\n const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);\n const [title, setTitle] = useState(currentTitle);\n const [about, setAbout] = useState(currentAbout);\n const [photo, setPhoto] = useState<File | undefined>();\n const [error, setError] = useState<string | undefined>();\n const imageHash = chat && getChatAvatarHash(chat);\n const currentAvatarBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl);\n const lang = useLang();\n\n useEffect(() => {\n if (progress === ManagementProgress.Complete) {\n setIsProfileFieldsTouched(false);\n setError(undefined);\n }\n }, [progress]);\n\n const adminsCount = (chat && chat.fullInfo && chat.fullInfo.adminMembers && chat.fullInfo.adminMembers.length) || 0;\n\n const handleClickEditType = useCallback(() => {\n onScreenSelect(ManagementScreens.ChatPrivacyType);\n }, [onScreenSelect]);\n\n const handleClickDiscussion = useCallback(() => {\n onScreenSelect(ManagementScreens.Discussion);\n }, [onScreenSelect]);\n\n const handleClickAdministrators = useCallback(() => {\n onScreenSelect(ManagementScreens.ChatAdministrators);\n }, [onScreenSelect]);\n\n const handleSetPhoto = useCallback((file: File) => {\n setPhoto(file);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleTitleChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setTitle(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleAboutChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {\n setAbout(e.target.value);\n setIsProfileFieldsTouched(true);\n }, []);\n\n const handleUpdateChannel = useCallback(() => {\n const trimmedTitle = title.trim();\n const trimmedAbout = about.trim();\n\n if (!trimmedTitle.length) {\n setError(CHANNEL_TITLE_EMPTY);\n return;\n }\n\n updateChat({\n chatId,\n title: trimmedTitle,\n about: trimmedAbout,\n photo,\n });\n }, [about, chatId, photo, title, updateChat]);\n\n const handleToggleSignatures = useCallback(() => {\n toggleSignatures({ chatId, isEnabled: !isSignaturesShown });\n }, [chatId, isSignaturesShown, toggleSignatures]);\n\n const handleClickSubscribers = useCallback(() => {\n onScreenSelect(ManagementScreens.ChannelSubscribers);\n }, [onScreenSelect]);\n\n\n const handleDeleteChannel = useCallback(() => {\n if (chat.isCreator) {\n deleteChannel({ chatId: chat.id });\n } else {\n leaveChannel({ chatId: chat.id });\n }\n\n closeDeleteDialog();\n closeManagement();\n openChat({ id: undefined });\n }, [chat.isCreator, chat.id, closeDeleteDialog, closeManagement, leaveChannel, deleteChannel, openChat]);\n\n if (chat.isRestricted) {\n return undefined;\n }\n\n const isLoading = progress === ManagementProgress.InProgress;\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <AvatarEditable\n currentAvatarBlobUrl={currentAvatarBlobUrl}\n onChange={handleSetPhoto}\n disabled={!canChangeInfo}\n />\n <InputText\n id=\"channel-title\"\n label={lang('EnterChannelName')}\n onChange={handleTitleChange}\n value={title}\n error={error === CHANNEL_TITLE_EMPTY ? error : undefined}\n disabled={!canChangeInfo}\n />\n <InputText\n id=\"channel-about\"\n className=\"mb-2\"\n label={lang('DescriptionPlaceholder')}\n onChange={handleAboutChange}\n value={about}\n disabled={!canChangeInfo}\n />\n {chat.isCreator && (\n <ListItem icon=\"lock\" ripple onClick={handleClickEditType}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelType')}</span>\n <span className=\"subtitle\">{chat.username ? lang('TypePublic') : lang('TypePrivate')}</span>\n </div>\n </ListItem>\n )}\n <ListItem icon=\"message\" ripple onClick={handleClickDiscussion} disabled={!canChangeInfo}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('Discussion')}</span>\n <span className=\"subtitle\">{hasLinkedChat ? lang('DiscussionUnlink') : lang('Add')}</span>\n </div>\n </ListItem>\n <ListItem icon=\"admin\" ripple onClick={handleClickAdministrators}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelAdministrators')}</span>\n <span className=\"subtitle\">{adminsCount}</span>\n </div>\n </ListItem>\n <div className=\"ListItem no-selection narrow\">\n <Checkbox\n checked={isSignaturesShown}\n label={lang('ChannelSignMessages')}\n onChange={handleToggleSignatures}\n />\n </div>\n </div>\n <div className=\"section\">\n <ListItem icon=\"group\" ripple onClick={handleClickSubscribers}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('ChannelSubscribers')}</span>\n <span className=\"subtitle\">{lang('Subscribers', chat.membersCount!, 'i')}</span>\n </div>\n </ListItem>\n </div>\n <div className=\"section\">\n <ListItem icon=\"delete\" ripple destructive onClick={openDeleteDialog}>\n {chat.isCreator ? lang('ChannelDelete') : lang('LeaveChannel')}\n </ListItem>\n </div>\n </div>\n <FloatingActionButton\n isShown={isProfileFieldsTouched}\n onClick={handleUpdateChannel}\n disabled={isLoading}\n ariaLabel={lang('Save')}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n <ConfirmDialog\n isOpen={isDeleteDialogOpen}\n onClose={closeDeleteDialog}\n text={chat.isCreator ? lang('ChannelDeleteAlert') : lang('ChannelLeaveAlert')}\n confirmLabel={chat.isCreator ? lang('ChannelDelete') : lang('LeaveChannel')}\n confirmHandler={handleDeleteChannel}\n confirmIsDestructive\n />\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const { progress } = global.management;\n const isSignaturesShown = Boolean(chat && chat.isSignaturesShown);\n\n return {\n chat,\n progress,\n isSignaturesShown,\n canChangeInfo: getHasAdminRight(chat, 'changeInfo'),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'toggleSignatures', 'updateChat', 'closeManagement', 'leaveChannel', 'deleteChannel', 'openChat',\n ]),\n)(ManageChannel));\n","import React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiChat } from '../../../api/types';\nimport { ManagementProgress } from '../../../types';\n\nimport { selectChat, selectManagement } from '../../../modules/selectors';\nimport { pick } from '../../../util/iteratees';\nimport { isChatChannel } from '../../../modules/helpers';\nimport useFlag from '../../../hooks/useFlag';\nimport useLang from '../../../hooks/useLang';\n\nimport SafeLink from '../../common/SafeLink';\nimport ListItem from '../../ui/ListItem';\nimport RadioGroup from '../../ui/RadioGroup';\nimport Loading from '../../ui/Loading';\nimport Spinner from '../../ui/Spinner';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport UsernameInput from '../../common/UsernameInput';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\ntype PrivacyType = 'private' | 'public';\n\ntype OwnProps = {\n chatId: number;\n};\n\ntype StateProps = {\n chat: ApiChat;\n isChannel: boolean;\n progress?: ManagementProgress;\n isUsernameAvailable?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, (\n 'checkPublicLink' | 'updatePublicLink' | 'updatePrivateLink'\n)>;\n\nconst ManageChatPrivacyType: FC<OwnProps & StateProps & DispatchProps> = ({\n chat,\n isChannel,\n progress,\n isUsernameAvailable,\n checkPublicLink,\n updatePublicLink,\n updatePrivateLink,\n}) => {\n const isPublic = Boolean(chat.username);\n const privateLink = chat.fullInfo && chat.fullInfo.inviteLink;\n\n const [privacyType, setPrivacyType] = useState<PrivacyType>(isPublic ? 'public' : 'private');\n const [username, setUsername] = useState();\n const [isRevokeConfirmDialogOpen, openRevokeConfirmDialog, closeRevokeConfirmDialog] = useFlag();\n\n const canUpdate = (\n (privacyType === 'public' && username && isUsernameAvailable)\n || (privacyType === 'private' && isPublic)\n );\n\n useEffect(() => {\n if (privacyType && !privateLink) {\n updatePrivateLink();\n }\n }, [privacyType, privateLink, updatePrivateLink]);\n\n const handleOptionChange = useCallback((value: string) => {\n setPrivacyType(value as PrivacyType);\n }, []);\n\n const handleSave = useCallback(() => {\n updatePublicLink({ username: privacyType === 'public' ? username : '' });\n }, [privacyType, updatePublicLink, username]);\n\n const handleRevokePrivateLink = useCallback(() => {\n closeRevokeConfirmDialog();\n updatePrivateLink();\n }, [closeRevokeConfirmDialog, updatePrivateLink]);\n\n const lang = useLang();\n const langPrefix1 = isChannel ? 'Channel' : 'Mega';\n const langPrefix2 = isChannel ? 'Channel' : 'Group';\n\n const options = [\n { value: 'private', label: lang(`${langPrefix1}Private`), subLabel: lang(`${langPrefix1}PrivateInfo`) },\n { value: 'public', label: lang(`${langPrefix1}Public`), subLabel: lang(`${langPrefix1}PublicInfo`) },\n ];\n\n const isLoading = progress === ManagementProgress.InProgress;\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <h3 className=\"section-heading\">{lang(`${langPrefix2}Type`)}</h3>\n <RadioGroup\n selected={privacyType}\n name=\"channel-type\"\n options={options}\n onChange={handleOptionChange}\n />\n </div>\n {privacyType === 'private' ? (\n <div className=\"section\">\n {privateLink ? (\n <>\n <SafeLink url={privateLink} className=\"group-link\" text={privateLink} />\n <p className=\"section-info\">{lang(`${langPrefix1}PrivateLinkHelp`)}</p>\n\n <ListItem icon=\"delete\" ripple destructive onClick={openRevokeConfirmDialog}>\n {lang('RevokeLink')}\n </ListItem>\n <ConfirmDialog\n isOpen={isRevokeConfirmDialogOpen}\n onClose={closeRevokeConfirmDialog}\n text={lang('RevokeAlert')}\n confirmLabel={lang('RevokeButton')}\n confirmHandler={handleRevokePrivateLink}\n confirmIsDestructive\n />\n </>\n ) : (\n <Loading />\n )}\n </div>\n ) : (\n <div className=\"section no-border\">\n <UsernameInput\n asLink\n currentUsername={chat.username}\n isLoading={isLoading}\n isUsernameAvailable={isUsernameAvailable}\n checkUsername={checkPublicLink}\n onChange={setUsername}\n />\n <p className=\"section-info\">\n {lang(`${langPrefix2}.Username.CreatePublicLinkHelp`)}\n </p>\n </div>\n )}\n </div>\n <FloatingActionButton\n isShown={canUpdate}\n disabled={isLoading}\n ariaLabel={lang('Save')}\n onClick={handleSave}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const { isUsernameAvailable } = selectManagement(global, chatId)!;\n\n return {\n chat,\n isChannel: isChatChannel(chat),\n progress: global.management.progress,\n isUsernameAvailable,\n };\n },\n (setGlobal, actions) => pick(actions, [\n 'checkPublicLink', 'updatePublicLink', 'updatePrivateLink',\n ]),\n)(ManageChatPrivacyType));\n","import React, {\n FC, memo, useCallback, useEffect, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { GlobalActions } from '../../../global/types';\nimport { ApiChat } from '../../../api/types';\nimport { ManagementScreens } from '../../../types';\n\nimport { STICKER_SIZE_DISCUSSION_GROUPS } from '../../../config';\nimport { selectChat } from '../../../modules/selectors';\nimport { pick } from '../../../util/iteratees';\nimport getAnimationData from '../../common/helpers/animatedAssets';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport NothingFound from '../../common/NothingFound';\nimport GroupChatInfo from '../../common/GroupChatInfo';\nimport AnimatedSticker from '../../common/AnimatedSticker';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\nimport useFlag from '../../../hooks/useFlag';\nimport renderText from '../../common/helpers/renderText';\nimport Avatar from '../../common/Avatar';\nimport { isChatChannel } from '../../../modules/helpers';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n chatsByIds: Record<number, ApiChat>;\n linkedChat?: ApiChat;\n forDiscussionIds?: number[];\n isChannel?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'loadGroupsForDiscussion' | 'linkDiscussionGroup' | 'unlinkDiscussionGroup'>;\n\nconst ManageDiscussion: FC<OwnProps & StateProps & DispatchProps> = ({\n chat,\n chatId,\n chatsByIds,\n linkedChat,\n forDiscussionIds,\n isChannel,\n onScreenSelect,\n loadGroupsForDiscussion,\n linkDiscussionGroup,\n unlinkDiscussionGroup,\n}) => {\n const [linkedGroupId, setLinkedGroupId] = useState<number>();\n const [animationData, setAnimationData] = useState<Record<string, any>>();\n const [isAnimationLoaded, setIsAnimationLoaded] = useState(false);\n const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []);\n const [isConfirmUnlinkGroupDialogOpen, openConfirmUnlinkGroupDialog, closeConfirmUnlinkGroupDialog] = useFlag();\n const [isConfirmLinkGroupDialogOpen, openConfirmLinkGroupDialog, closeConfirmLinkGroupDialog] = useFlag();\n const lang = useLang();\n const linkedChatId = linkedChat && linkedChat.id;\n\n useEffect(() => {\n loadGroupsForDiscussion();\n }, [loadGroupsForDiscussion]);\n\n useEffect(() => {\n if (!animationData) {\n getAnimationData('DiscussionGroups').then(setAnimationData);\n }\n }, [animationData]);\n\n const handleUnlinkGroupSessions = useCallback(() => {\n closeConfirmUnlinkGroupDialog();\n unlinkDiscussionGroup({ channelId: isChannel ? chatId : linkedChatId });\n if (!isChannel) {\n onScreenSelect(ManagementScreens.Initial);\n }\n }, [closeConfirmUnlinkGroupDialog, unlinkDiscussionGroup, isChannel, chatId, linkedChatId, onScreenSelect]);\n\n const handleLinkGroupSessions = useCallback(() => {\n closeConfirmLinkGroupDialog();\n linkDiscussionGroup({ channelId: chatId, chatId: linkedGroupId });\n }, [closeConfirmLinkGroupDialog, linkDiscussionGroup, chatId, linkedGroupId]);\n\n const onDiscussionClick = (groupId: number) => {\n setLinkedGroupId(groupId);\n openConfirmLinkGroupDialog();\n };\n\n function renderUnlinkGroupHeader() {\n return (\n <div className=\"modal-header\">\n <Avatar\n size=\"tiny\"\n chat={linkedChat}\n />\n <div className=\"modal-title\">\n {lang(isChannel ? 'DiscussionUnlinkGroup' : 'DiscussionUnlinkChannel')}\n </div>\n </div>\n );\n }\n function renderLinkGroupHeader() {\n const linkedGroup = chatsByIds[linkedGroupId];\n\n if (!linkedGroup) {\n return undefined;\n }\n\n return (\n <div className=\"modal-header\">\n <Avatar\n size=\"tiny\"\n chat={linkedGroup}\n />\n <div className=\"modal-title\">\n {lang('Channel.DiscussionGroup.LinkGroup')}\n </div>\n </div>\n );\n }\n\n function renderLinkGroupConfirmText() {\n const linkedGroup = chatsByIds[linkedGroupId];\n\n if (!linkedGroup) {\n return undefined;\n }\n\n if (linkedGroup.hasPrivateLink) {\n return renderText(\n `Do you want to make **${linkedGroup.title}** the discussion board for **${chat!.title}**?`,\n ['br', 'simple_markdown'],\n );\n // return renderText(\n // lang('DiscussionLinkGroupPublicAlert', linkedChat.title, chat!.title),\n // ['br', 'simple_markdown'],\n // );\n }\n\n return renderText(\n // eslint-disable-next-line max-len\n `Do you want to make **${linkedGroup.title}** the discussion board for **${chat!.title}**?\\n\\nAnyone from the channel will be able to see messages in this group.`,\n ['br', 'simple_markdown'],\n );\n // return renderText(\n // lang('DiscussionLinkGroupPrivateAlert', linkedChat.title, chat!.title),\n // ['br', 'simple_markdown'],\n // );\n }\n\n function renderLinkedGroup() {\n return (\n <div>\n <ListItem\n className=\"chat-item-clickable\"\n inactive\n >\n <GroupChatInfo chatId={linkedChat!.id} />\n </ListItem>\n <ListItem\n icon=\"delete\"\n ripple\n destructive\n onClick={openConfirmUnlinkGroupDialog}\n >\n {lang(isChannel ? 'DiscussionUnlinkGroup' : 'DiscussionUnlinkChannel')}\n </ListItem>\n <ConfirmDialog\n isOpen={isConfirmUnlinkGroupDialogOpen}\n onClose={closeConfirmUnlinkGroupDialog}\n header={renderUnlinkGroupHeader()}\n textParts={renderText(\n lang(isChannel ? 'DiscussionUnlinkChannelAlert' : 'DiscussionUnlinkGroupAlert', linkedChat!.title),\n ['br', 'simple_markdown'],\n )}\n confirmLabel={lang(isChannel ? 'DiscussionUnlinkGroup' : 'DiscussionUnlinkChannel')}\n confirmHandler={handleUnlinkGroupSessions}\n confirmIsDestructive\n />\n </div>\n );\n }\n\n function renderDiscussionGroups() {\n return (\n <div>\n <p className=\"section-help\">{lang('DiscussionChannelHelp')}</p>\n\n <div teactFastList>\n <ListItem\n key=\"create-group\"\n icon=\"group\"\n ripple\n teactOrderKey={0}\n className=\"not-implemented\"\n >\n {lang('DiscussionCreateGroup')}\n </ListItem>\n {forDiscussionIds ? (\n forDiscussionIds.map((id, i) => (\n <ListItem\n key={id}\n teactOrderKey={i + 1}\n className=\"chat-item-clickable scroll-item\"\n onClick={() => { onDiscussionClick(id); }}\n >\n <GroupChatInfo chatId={id} />\n </ListItem>\n ))\n ) : (\n <NothingFound key=\"nothing-found\" teactOrderKey={0} text=\"No discussion groups found\" />\n )}\n </div>\n <p className=\"mt-4 mb-0 section-help\">{lang('DiscussionChannelHelp2')}</p>\n <ConfirmDialog\n isOpen={isConfirmLinkGroupDialogOpen}\n onClose={closeConfirmLinkGroupDialog}\n header={renderLinkGroupHeader()}\n textParts={renderLinkGroupConfirmText()}\n confirmLabel={lang('DiscussionLinkGroup')}\n confirmHandler={handleLinkGroupSessions}\n isButtonsInOneRow\n />\n </div>\n );\n }\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <div className=\"section-icon\">\n {animationData && (\n <AnimatedSticker\n id=\"discussionGroupsDucks\"\n size={STICKER_SIZE_DISCUSSION_GROUPS}\n animationData={animationData}\n play={isAnimationLoaded}\n noLoop\n onLoad={handleAnimationLoad}\n />\n )}\n </div>\n {linkedChat && renderLinkedGroup()}\n {!linkedChat && renderDiscussionGroups()}\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const { forDiscussionIds, byId: chatsByIds } = global.chats;\n const linkedChat = chat && chat.fullInfo && chat.fullInfo.linkedChatId\n ? selectChat(global, chat.fullInfo.linkedChatId)\n : undefined;\n\n return {\n chat,\n chatsByIds,\n forDiscussionIds,\n linkedChat,\n isChannel: chat && isChatChannel(chat),\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'loadGroupsForDiscussion', 'linkDiscussionGroup', 'unlinkDiscussionGroup',\n ]),\n)(ManageDiscussion));\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiChatBannedRights } from '../../../api/types';\nimport { ManagementScreens } from '../../../types';\nimport { GlobalActions } from '../../../global/types';\n\nimport { pick } from '../../../util/iteratees';\nimport { selectChat } from '../../../modules/selectors';\nimport useLang from '../../../hooks/useLang';\nimport useFlag from '../../../hooks/useFlag';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\n\ntype OwnProps = {\n chatId: number;\n selectedChatMemberId?: number;\n isPromotedByCurrentUser?: boolean;\n onScreenSelect: (screen: ManagementScreens) => void;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n isFormFullyDisabled?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'updateChatMemberBannedRights'>;\n\nconst ManageGroupUserPermissions: FC<OwnProps & StateProps & DispatchProps> = ({\n chat,\n selectedChatMemberId,\n onScreenSelect,\n updateChatMemberBannedRights,\n isFormFullyDisabled,\n}) => {\n const [permissions, setPermissions] = useState<ApiChatBannedRights>({});\n const [havePermissionChanged, setHavePermissionChanged] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [isBanConfirmationDialogOpen, openBanConfirmationDialog, closeBanConfirmationDialog] = useFlag();\n const lang = useLang();\n\n const selectedChatMember = useMemo(() => {\n if (!chat || !chat.fullInfo || !chat.fullInfo.members) {\n return undefined;\n }\n\n return chat.fullInfo.members.find(({ userId }) => userId === selectedChatMemberId);\n }, [chat, selectedChatMemberId]);\n\n useEffect(() => {\n if (chat && chat.fullInfo && selectedChatMemberId && !selectedChatMember) {\n onScreenSelect(ManagementScreens.GroupPermissions);\n }\n }, [chat, onScreenSelect, selectedChatMember, selectedChatMemberId]);\n\n useEffect(() => {\n setPermissions((selectedChatMember && selectedChatMember.bannedRights) || (chat && chat.defaultBannedRights) || {});\n setHavePermissionChanged(false);\n setIsLoading(false);\n }, [chat, selectedChatMember]);\n\n const handlePermissionChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { name } = e.target;\n\n function getUpdatedPermissionValue(value: true | undefined) {\n return value ? undefined : true;\n }\n\n setPermissions((p) => ({\n ...p,\n [name]: getUpdatedPermissionValue(p[name as keyof ApiChatBannedRights]),\n ...(name === 'sendStickers' && {\n sendGifs: getUpdatedPermissionValue(p[name]),\n }),\n }));\n setHavePermissionChanged(true);\n }, []);\n\n const handleSavePermissions = useCallback(() => {\n if (!chat || !selectedChatMemberId) {\n return;\n }\n\n setIsLoading(true);\n updateChatMemberBannedRights({\n chatId: chat.id,\n userId: selectedChatMemberId,\n bannedRights: permissions,\n });\n }, [chat, selectedChatMemberId, permissions, updateChatMemberBannedRights]);\n\n const handleBanFromGroup = useCallback(() => {\n if (!chat || !selectedChatMemberId) {\n return;\n }\n\n updateChatMemberBannedRights({\n chatId: chat.id,\n userId: selectedChatMemberId,\n bannedRights: {\n viewMessages: true,\n },\n });\n }, [chat, selectedChatMemberId, updateChatMemberBannedRights]);\n\n const getControlIsDisabled = useCallback((key: keyof ApiChatBannedRights) => {\n if (isFormFullyDisabled) {\n return true;\n }\n\n if (!chat || !chat.defaultBannedRights) {\n return false;\n }\n\n return chat.defaultBannedRights[key];\n }, [chat, isFormFullyDisabled]);\n\n if (!selectedChatMember) {\n return undefined;\n }\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <ListItem inactive className=\"chat-item-clickable\">\n <PrivateChatInfo userId={selectedChatMember.userId} />\n </ListItem>\n\n <h3 className=\"section-heading mt-4\">{lang('UserRestrictionsCanDo')}</h3>\n\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendMessages\"\n checked={!permissions.sendMessages}\n label={lang('UserRestrictionsSend')}\n blocking\n disabled={getControlIsDisabled('sendMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendMedia\"\n checked={!permissions.sendMedia}\n label={lang('UserRestrictionsSendMedia')}\n blocking\n disabled={getControlIsDisabled('sendMedia')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendStickers\"\n checked={!permissions.sendStickers && !permissions.sendGifs}\n label={lang('UserRestrictionsSendStickers')}\n blocking\n disabled={getControlIsDisabled('sendStickers')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"sendPolls\"\n checked={!permissions.sendPolls}\n label={lang('UserRestrictionsSendPolls')}\n blocking\n disabled={getControlIsDisabled('sendPolls')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"embedLinks\"\n checked={!permissions.embedLinks}\n label={lang('UserRestrictionsEmbedLinks')}\n blocking\n disabled={getControlIsDisabled('embedLinks')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"inviteUsers\"\n checked={!permissions.inviteUsers}\n label={lang('UserRestrictionsInviteUsers')}\n blocking\n disabled={getControlIsDisabled('inviteUsers')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"pinMessages\"\n checked={!permissions.pinMessages}\n label={lang('UserRestrictionsPinMessages')}\n blocking\n disabled={getControlIsDisabled('pinMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!permissions.changeInfo}\n label={lang('UserRestrictionsChangeInfo')}\n blocking\n disabled={getControlIsDisabled('changeInfo')}\n onChange={handlePermissionChange}\n />\n </div>\n </div>\n\n {!isFormFullyDisabled && (\n <div className=\"section\">\n <ListItem icon=\"delete-user\" ripple destructive onClick={openBanConfirmationDialog}>\n {lang('UserRestrictionsBlock')}\n </ListItem>\n </div>\n )}\n </div>\n\n <FloatingActionButton\n isShown={havePermissionChanged}\n onClick={handleSavePermissions}\n ariaLabel={lang('Save')}\n disabled={isLoading}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n\n <ConfirmDialog\n isOpen={isBanConfirmationDialogOpen}\n onClose={closeBanConfirmationDialog}\n text=\"Are you sure you want to ban and remove this user from the group?\"\n confirmLabel=\"Remove\"\n confirmHandler={handleBanFromGroup}\n confirmIsDestructive\n />\n </div>\n );\n};\n\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId, isPromotedByCurrentUser }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const isFormFullyDisabled = !(chat.isCreator || isPromotedByCurrentUser);\n\n return { chat, isFormFullyDisabled };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['updateChatMemberBannedRights']),\n)(ManageGroupUserPermissions));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ManagementScreens } from '../../../types';\nimport { ApiChat, ApiChatMember, ApiUser } from '../../../api/types';\nimport { getUserFullName, isChatChannel } from '../../../modules/helpers';\n\nimport { selectChat } from '../../../modules/selectors';\nimport useLang from '../../../hooks/useLang';\n\nimport ListItem from '../../ui/ListItem';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n onChatMemberSelect: (memberId: number, isPromotedByCurrentUser?: boolean) => void;\n};\n\ntype StateProps = {\n chat: ApiChat;\n currentUserId?: number;\n isChannel: boolean;\n usersById: Record<number, ApiUser>;\n};\n\nconst ManageChatAdministrators: FC<OwnProps & StateProps> = ({\n chat,\n isChannel,\n currentUserId,\n usersById,\n onScreenSelect,\n onChatMemberSelect,\n}) => {\n const lang = useLang();\n\n function handleRecentActionsClick() {\n onScreenSelect(ManagementScreens.GroupRecentActions);\n }\n\n const adminMembers = useMemo(() => {\n if (!chat.fullInfo || !chat.fullInfo.adminMembers) {\n return [];\n }\n\n return chat.fullInfo.adminMembers.sort((a, b) => {\n if (a.isOwner) {\n return -1;\n } else if (b.isOwner) {\n return 1;\n }\n\n return 0;\n });\n }, [chat]);\n\n const handleAdminMemberClick = useCallback((member: ApiChatMember) => {\n onChatMemberSelect(member.userId, member.promotedByUserId === currentUserId);\n onScreenSelect(ManagementScreens.ChatAdminRights);\n }, [currentUserId, onChatMemberSelect, onScreenSelect]);\n\n const getMemberStatus = useCallback((member: ApiChatMember) => {\n if (member.isOwner) {\n return lang('ChannelCreator');\n }\n\n const promotedByUser = member.promotedByUserId ? usersById[member.promotedByUserId] : undefined;\n\n if (promotedByUser) {\n return lang('EditAdminPromotedBy', getUserFullName(promotedByUser));\n }\n\n return lang('ChannelAdmin');\n }, [lang, usersById]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <ListItem icon=\"recent\" ripple onClick={handleRecentActionsClick}>\n <div className=\"multiline-item\">\n <span className=\"title\">{lang('EventLog')}</span>\n <span className=\"subtitle\">{lang(isChannel ? 'EventLogInfoDetailChannel' : 'EventLogInfoDetail')}</span>\n </div>\n </ListItem>\n </div>\n\n <div className=\"section\">\n <p className=\"text-muted\">\n {isChannel\n ? 'You can add administrators to help you manage your channel.'\n : 'You can add administrators to help you manage your group.'}\n </p>\n\n {adminMembers.map((member) => (\n <ListItem\n key={member.userId}\n className=\"chat-item-clickable\"\n ripple\n onClick={() => handleAdminMemberClick(member)}\n >\n <PrivateChatInfo\n userId={member.userId}\n status={getMemberStatus(member)}\n forceShowSelf\n />\n </ListItem>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const { byId: usersById } = global.users;\n\n return {\n chat,\n currentUserId: global.currentUserId,\n isChannel: isChatChannel(chat),\n usersById,\n };\n },\n // (setGlobal, actions): DispatchProps => pick(actions, ['togglePreHistoryHidden', 'updateChat']),\n)(ManageChatAdministrators));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiChatMember } from '../../../api/types';\nimport useLang from '../../../hooks/useLang';\nimport { selectChat } from '../../../modules/selectors';\n\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\n\ntype OwnProps = {\n chatId: number;\n};\n\ntype StateProps = {\n chat?: ApiChat;\n};\n\nconst ManageGroupRecentActions: FC<OwnProps & StateProps> = ({ chat }) => {\n const lang = useLang();\n\n const adminMembers = useMemo(() => {\n if (!chat || !chat.fullInfo || !chat.fullInfo.adminMembers) {\n return [];\n }\n\n return chat.fullInfo.adminMembers.sort((a, b) => {\n if (a.isOwner) {\n return -1;\n } else if (b.isOwner) {\n return 1;\n }\n\n return 0;\n });\n }, [chat]);\n\n const getMemberStatus = useCallback((member: ApiChatMember) => {\n if (member.isOwner) {\n return lang('ChannelCreator');\n }\n\n return lang('ChannelAdmin');\n }, [lang]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section not-implemented\">\n <h3 className=\"section-heading\">Actions</h3>\n\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogAllEvents')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterNewAdmins')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterNewMembers')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterChannelInfo')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterDeletedMessages')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterEditedMessages')}\n onChange={undefined}\n />\n </div>\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogFilterLeavingMembers')}\n onChange={undefined}\n />\n </div>\n </div>\n\n <div className=\"section not-implemented\">\n <h3 className=\"section-heading\">Admins</h3>\n\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!false}\n label={lang('EventLogAllAdmins')}\n onChange={undefined}\n />\n </div>\n\n {adminMembers.map((member) => (\n <ListItem\n key={member.userId}\n className=\"chat-item-clickable picker-list-item\"\n onClick={undefined}\n ripple\n >\n <Checkbox label=\"\" checked={!false} />\n <PrivateChatInfo\n userId={member.userId}\n status={getMemberStatus(member)}\n forceShowSelf\n />\n </ListItem>\n ))}\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n\n return { chat };\n },\n)(ManageGroupRecentActions));\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChat, ApiChatAdminRights, ApiUser } from '../../../api/types';\nimport { ManagementScreens } from '../../../types';\nimport { GlobalActions } from '../../../global/types';\n\nimport { pick } from '../../../util/iteratees';\nimport { selectChat } from '../../../modules/selectors';\nimport { getUserFullName, isChatBasicGroup, isChatChannel } from '../../../modules/helpers';\nimport useLang from '../../../hooks/useLang';\nimport useFlag from '../../../hooks/useFlag';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport ListItem from '../../ui/ListItem';\nimport Checkbox from '../../ui/Checkbox';\nimport FloatingActionButton from '../../ui/FloatingActionButton';\nimport Spinner from '../../ui/Spinner';\nimport ConfirmDialog from '../../ui/ConfirmDialog';\nimport InputText from '../../ui/InputText';\n\ntype OwnProps = {\n chatId: number;\n selectedChatMemberId?: number;\n isPromotedByCurrentUser?: boolean;\n onScreenSelect: (screen: ManagementScreens) => void;\n};\n\ntype StateProps = {\n chat: ApiChat;\n usersById: Record<number, ApiUser>;\n currentUserId?: number;\n isChannel: boolean;\n isFormFullyDisabled: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'updateChatAdmin'>;\n\nconst CUSTOM_TITLE_MAX_LENGTH = 16;\n\nconst ManageGroupAdminRights: FC<OwnProps & StateProps & DispatchProps> = ({\n selectedChatMemberId,\n onScreenSelect,\n chat,\n usersById,\n currentUserId,\n isChannel,\n isFormFullyDisabled,\n updateChatAdmin,\n}) => {\n const [permissions, setPermissions] = useState<ApiChatAdminRights>({});\n const [isTouched, setIsTouched] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [isDismissConfirmationDialogOpen, openDismissConfirmationDialog, closeDismissConfirmationDialog] = useFlag();\n const [customTitle, setCustomTitle] = useState('');\n const lang = useLang();\n\n const selectedChatMember = useMemo(() => {\n if (!chat.fullInfo || !chat.fullInfo.adminMembers) {\n return undefined;\n }\n\n return chat.fullInfo.adminMembers.find(({ userId }) => userId === selectedChatMemberId);\n }, [chat, selectedChatMemberId]);\n\n useEffect(() => {\n if (chat && chat.fullInfo && selectedChatMemberId && !selectedChatMember) {\n onScreenSelect(ManagementScreens.ChatAdministrators);\n }\n }, [chat, onScreenSelect, selectedChatMember, selectedChatMemberId]);\n\n useEffect(() => {\n setPermissions((selectedChatMember && selectedChatMember.adminRights) || {});\n setCustomTitle(((selectedChatMember && selectedChatMember.customTitle) || '').substr(0, CUSTOM_TITLE_MAX_LENGTH));\n setIsTouched(false);\n setIsLoading(false);\n }, [selectedChatMember]);\n\n const handlePermissionChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const { name } = e.target;\n\n function getUpdatedPermissionValue(value: true | undefined) {\n return value ? undefined : true;\n }\n\n setPermissions((p) => ({\n ...p,\n [name]: getUpdatedPermissionValue(p[name as keyof ApiChatAdminRights]),\n }));\n setIsTouched(true);\n }, []);\n\n const handleSavePermissions = useCallback(() => {\n if (!selectedChatMemberId) {\n return;\n }\n\n setIsLoading(true);\n updateChatAdmin({\n chatId: chat.id,\n userId: selectedChatMemberId,\n adminRights: permissions,\n customTitle,\n });\n }, [chat, selectedChatMemberId, permissions, customTitle, updateChatAdmin]);\n\n const handleDismissAdmin = useCallback(() => {\n if (!selectedChatMemberId) {\n return;\n }\n\n updateChatAdmin({\n chatId: chat.id,\n userId: selectedChatMemberId,\n adminRights: {},\n });\n closeDismissConfirmationDialog();\n }, [chat.id, closeDismissConfirmationDialog, selectedChatMemberId, updateChatAdmin]);\n\n const getControlIsDisabled = useCallback((key: keyof ApiChatAdminRights) => {\n if (isChatBasicGroup(chat)) {\n return false;\n }\n\n if (isFormFullyDisabled || !chat.adminRights) {\n return true;\n }\n\n return !chat.adminRights![key];\n }, [chat, isFormFullyDisabled]);\n\n const memberStatus = useMemo(() => {\n if (!selectedChatMember) {\n return undefined;\n }\n\n if (selectedChatMember.isOwner) {\n return lang('ChannelCreator');\n }\n\n const promotedByUser = selectedChatMember.promotedByUserId\n ? usersById[selectedChatMember.promotedByUserId]\n : undefined;\n\n if (promotedByUser) {\n return lang('EditAdminPromotedBy', getUserFullName(promotedByUser));\n }\n\n return lang('ChannelAdmin');\n }, [selectedChatMember, usersById, lang]);\n\n const handleCustomTitleChange = useCallback((e) => {\n const { value } = e.target;\n setCustomTitle(value);\n setIsTouched(true);\n }, []);\n\n if (!selectedChatMember) {\n return undefined;\n }\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\">\n <ListItem inactive className=\"chat-item-clickable\">\n <PrivateChatInfo\n userId={selectedChatMember.userId}\n status={memberStatus}\n forceShowSelf\n />\n </ListItem>\n\n <h3 className=\"section-heading mt-4\">{lang('EditAdminWhatCanDo')}</h3>\n\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"changeInfo\"\n checked={!!permissions.changeInfo}\n label={lang(isChannel ? 'EditAdminChangeChannelInfo' : 'EditAdminChangeGroupInfo')}\n blocking\n disabled={getControlIsDisabled('changeInfo')}\n onChange={handlePermissionChange}\n />\n </div>\n {isChannel && (\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"postMessages\"\n checked={!!permissions.postMessages}\n label={lang('EditAdminPostMessages')}\n blocking\n disabled={getControlIsDisabled('postMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n )}\n {isChannel && (\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"editMessages\"\n checked={!!permissions.editMessages}\n label={lang('EditAdminEditMessages')}\n blocking\n disabled={getControlIsDisabled('editMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n )}\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"deleteMessages\"\n checked={!!permissions.deleteMessages}\n label={lang(isChannel ? 'EditAdminDeleteMessages' : 'EditAdminGroupDeleteMessages')}\n blocking\n disabled={getControlIsDisabled('deleteMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n {!isChannel && (\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"banUsers\"\n checked={!!permissions.banUsers}\n label={lang('EditAdminBanUsers')}\n blocking\n disabled={getControlIsDisabled('banUsers')}\n onChange={handlePermissionChange}\n />\n </div>\n )}\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"inviteUsers\"\n checked={!!permissions.inviteUsers}\n label={lang('EditAdminAddUsers')}\n blocking\n disabled={getControlIsDisabled('inviteUsers')}\n onChange={handlePermissionChange}\n />\n </div>\n {!isChannel && (\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"pinMessages\"\n checked={!!permissions.pinMessages}\n label={lang('EditAdminPinMessages')}\n blocking\n disabled={getControlIsDisabled('pinMessages')}\n onChange={handlePermissionChange}\n />\n </div>\n )}\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"addAdmins\"\n checked={!!permissions.addAdmins}\n label={lang('EditAdminAddAdmins')}\n blocking\n disabled={getControlIsDisabled('addAdmins')}\n onChange={handlePermissionChange}\n />\n </div>\n {!isChannel && (\n <div className=\"ListItem no-selection\">\n <Checkbox\n name=\"anonymous\"\n checked={!!permissions.anonymous}\n label={lang('EditAdminSendAnonymously')}\n blocking\n disabled={getControlIsDisabled('anonymous')}\n onChange={handlePermissionChange}\n />\n </div>\n )}\n\n {isFormFullyDisabled && (\n <p className=\"section-info mb-4\">\n {lang('Channel.EditAdmin.CannotEdit')}\n </p>\n )}\n\n {!isChannel && (\n <InputText\n id=\"admin-title\"\n label={lang('EditAdminRank')}\n onChange={handleCustomTitleChange}\n value={customTitle}\n disabled={isFormFullyDisabled}\n maxLength={CUSTOM_TITLE_MAX_LENGTH}\n />\n )}\n\n {currentUserId !== selectedChatMemberId && !isFormFullyDisabled && (\n <ListItem icon=\"delete\" ripple destructive onClick={openDismissConfirmationDialog}>\n {lang('EditAdminRemoveAdmin')}\n </ListItem>\n )}\n </div>\n </div>\n\n <FloatingActionButton\n isShown={isTouched}\n onClick={handleSavePermissions}\n ariaLabel={lang('Save')}\n disabled={isLoading}\n >\n {isLoading ? (\n <Spinner color=\"white\" />\n ) : (\n <i className=\"icon-check\" />\n )}\n </FloatingActionButton>\n\n <ConfirmDialog\n isOpen={isDismissConfirmationDialogOpen}\n onClose={closeDismissConfirmationDialog}\n text=\"Are you sure you want to dismiss this admin?\"\n confirmLabel=\"Dismiss\"\n confirmHandler={handleDismissAdmin}\n confirmIsDestructive\n />\n </div>\n );\n};\n\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId, isPromotedByCurrentUser }): StateProps => {\n const chat = selectChat(global, chatId)!;\n const { byId: usersById } = global.users;\n const { currentUserId } = global;\n const isChannel = isChatChannel(chat);\n const isFormFullyDisabled = !(chat.isCreator || isPromotedByCurrentUser);\n\n return {\n chat,\n usersById,\n currentUserId,\n isChannel,\n isFormFullyDisabled,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, ['updateChatAdmin']),\n)(ManageGroupAdminRights));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChatMember, ApiUser } from '../../../api/types';\nimport { GlobalActions } from '../../../global/types';\nimport { selectChat } from '../../../modules/selectors';\nimport { getSortedUserIds, isChatChannel } from '../../../modules/helpers';\nimport { pick } from '../../../util/iteratees';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport NothingFound from '../../common/NothingFound';\nimport ListItem from '../../ui/ListItem';\n\ntype OwnProps = {\n chatId: number;\n};\n\ntype StateProps = {\n usersById: Record<number, ApiUser>;\n members?: ApiChatMember[];\n isChannel?: boolean;\n};\n\ntype DispatchProps = Pick<GlobalActions, 'openUserInfo'>;\n\nconst ManageGroupMembers: FC<OwnProps & StateProps & DispatchProps> = ({\n members,\n usersById,\n isChannel,\n openUserInfo,\n}) => {\n const memberIds = useMemo(() => {\n if (!members || !usersById) {\n return undefined;\n }\n\n return getSortedUserIds(members.map(({ userId }) => userId), usersById);\n }, [members, usersById]);\n\n const handleMemberClick = useCallback((id: number) => {\n openUserInfo({ id });\n }, [openUserInfo]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\" teactFastList>\n {memberIds ? (\n memberIds.map((id, i) => (\n <ListItem\n key={id}\n teactOrderKey={i}\n className=\"chat-item-clickable scroll-item\"\n onClick={() => handleMemberClick(id)}\n >\n <PrivateChatInfo userId={id} forceShowSelf />\n </ListItem>\n ))\n ) : (\n <NothingFound\n teactOrderKey={0}\n key=\"nothing-found\"\n text={isChannel ? 'No subscribers found' : 'No members found'}\n />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const { byId: usersById } = global.users;\n const members = chat && chat.fullInfo && chat.fullInfo.members;\n const isChannel = chat && isChatChannel(chat);\n\n return {\n members,\n usersById,\n isChannel,\n };\n },\n (setGlobal, actions): DispatchProps => pick(actions, [\n 'openUserInfo',\n ]),\n)(ManageGroupMembers));\n","import React, {\n FC, memo, useCallback, useMemo,\n} from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ApiChatMember, ApiUser } from '../../../api/types';\nimport { ManagementScreens } from '../../../types';\n\nimport { selectChat } from '../../../modules/selectors';\nimport { getSortedUserIds, isChatChannel } from '../../../modules/helpers';\n\nimport PrivateChatInfo from '../../common/PrivateChatInfo';\nimport ListItem from '../../ui/ListItem';\nimport NothingFound from '../../common/NothingFound';\n\ntype OwnProps = {\n chatId: number;\n onScreenSelect: (screen: ManagementScreens) => void;\n onChatMemberSelect: (memberId: number) => void;\n};\n\ntype StateProps = {\n usersById: Record<number, ApiUser>;\n members?: ApiChatMember[];\n isChannel?: boolean;\n};\n\nconst ManageGroupUserPermissionsCreate: FC<OwnProps & StateProps> = ({\n usersById,\n members,\n isChannel,\n onScreenSelect,\n onChatMemberSelect,\n}) => {\n const memberIds = useMemo(() => {\n if (!members || !usersById) {\n return undefined;\n }\n\n return getSortedUserIds(members.filter((member) => !member.isOwner).map(({ userId }) => userId), usersById);\n }, [members, usersById]);\n\n const handleExceptionMemberClick = useCallback((memberId: number) => {\n onChatMemberSelect(memberId);\n onScreenSelect(ManagementScreens.GroupUserPermissions);\n }, [onChatMemberSelect, onScreenSelect]);\n\n return (\n <div className=\"Management\">\n <div className=\"custom-scroll\">\n <div className=\"section\" teactFastList>\n {memberIds ? (\n memberIds.map((id, i) => (\n <ListItem\n key={id}\n teactOrderKey={i}\n className=\"chat-item-clickable scroll-item\"\n onClick={() => handleExceptionMemberClick(id)}\n >\n <PrivateChatInfo userId={id} forceShowSelf />\n </ListItem>\n ))\n ) : (\n <NothingFound\n teactOrderKey={0}\n key=\"nothing-found\"\n text={isChannel ? 'No subscribers found' : 'No members found'}\n />\n )}\n </div>\n </div>\n </div>\n );\n};\n\n\nexport default memo(withGlobal<OwnProps>(\n (global, { chatId }): StateProps => {\n const chat = selectChat(global, chatId);\n const { byId: usersById } = global.users;\n const members = chat && chat.fullInfo && chat.fullInfo.members;\n const isChannel = chat && isChatChannel(chat);\n\n return {\n members,\n usersById,\n isChannel,\n };\n },\n)(ManageGroupUserPermissionsCreate));\n","import React, { FC, memo } from '../../../lib/teact/teact';\nimport { withGlobal } from '../../../lib/teact/teactn';\n\nimport { ManagementScreens, ManagementType } from '../../../types';\n\nimport { selectCurrentManagementType } from '../../../modules/selectors';\n\nimport ManageUser from './ManageUser';\nimport ManageGroup from './ManageGroup';\nimport ManageGroupPermissions from './ManageGroupPermissions';\nimport ManageGroupRemovedUsers from './ManageGroupRemovedUsers';\nimport ManageChannel from './ManageChannel';\nimport ManageChatPrivacyType from './ManageChatPrivacyType';\nimport ManageDiscussion from './ManageDiscussion';\nimport ManageGroupUserPermissions from './ManageGroupUserPermissions';\nimport ManageChatAdministrators from './ManageChatAdministrators';\nimport ManageGroupRecentActions from './ManageGroupRecentActions';\nimport ManageGroupAdminRights from './ManageGroupAdminRights';\nimport ManageGroupMembers from './ManageGroupMembers';\nimport ManageGroupUserPermissionsCreate from './ManageGroupUserPermissionsCreate';\n\nexport type OwnProps = {\n chatId: number;\n currentScreen: ManagementScreens;\n selectedChatMemberId?: number;\n isPromotedByCurrentUser?: boolean;\n onScreenSelect: (screen: ManagementScreens) => void;\n onChatMemberSelect: (memberId: number, isPromotedByCurrentUser?: boolean) => void;\n};\n\ntype StateProps = {\n managementType?: ManagementType;\n};\n\nconst Management: FC<OwnProps & StateProps> = ({\n chatId,\n currentScreen,\n selectedChatMemberId,\n isPromotedByCurrentUser,\n onScreenSelect,\n onChatMemberSelect,\n managementType,\n}) => {\n switch (currentScreen) {\n case ManagementScreens.Initial: {\n switch (managementType) {\n case 'user':\n return <ManageUser key={chatId} userId={chatId} />;\n case 'group':\n return <ManageGroup key={chatId} chatId={chatId} onScreenSelect={onScreenSelect} />;\n case 'channel':\n return <ManageChannel key={chatId} chatId={chatId} onScreenSelect={onScreenSelect} />;\n }\n\n break;\n }\n\n case ManagementScreens.ChatPrivacyType:\n return (\n <ManageChatPrivacyType chatId={chatId} />\n );\n\n case ManagementScreens.Discussion:\n return (\n <ManageDiscussion\n chatId={chatId}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case ManagementScreens.GroupPermissions:\n return (\n <ManageGroupPermissions\n chatId={chatId}\n onScreenSelect={onScreenSelect}\n onChatMemberSelect={onChatMemberSelect}\n />\n );\n\n case ManagementScreens.GroupRemovedUsers:\n return (\n <ManageGroupRemovedUsers chatId={chatId} />\n );\n\n case ManagementScreens.GroupUserPermissionsCreate:\n return (\n <ManageGroupUserPermissionsCreate\n chatId={chatId}\n onChatMemberSelect={onChatMemberSelect}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case ManagementScreens.GroupUserPermissions:\n return (\n <ManageGroupUserPermissions\n chatId={chatId}\n selectedChatMemberId={selectedChatMemberId}\n isPromotedByCurrentUser={isPromotedByCurrentUser}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case ManagementScreens.ChatAdministrators:\n return (\n <ManageChatAdministrators\n chatId={chatId}\n onScreenSelect={onScreenSelect}\n onChatMemberSelect={onChatMemberSelect}\n />\n );\n\n case ManagementScreens.GroupRecentActions:\n return (\n <ManageGroupRecentActions\n chatId={chatId}\n />\n );\n\n case ManagementScreens.ChatAdminRights:\n return (\n <ManageGroupAdminRights\n chatId={chatId}\n selectedChatMemberId={selectedChatMemberId}\n isPromotedByCurrentUser={isPromotedByCurrentUser}\n onScreenSelect={onScreenSelect}\n />\n );\n\n case ManagementScreens.ChannelSubscribers:\n case ManagementScreens.GroupMembers:\n return (\n <ManageGroupMembers chatId={chatId} />\n );\n }\n\n return undefined; // Never reached\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const managementType = selectCurrentManagementType(global);\n\n return {\n managementType,\n };\n },\n)(Management));\n","const CURRENCIES: Record<string, string> = {\n USD: '$',\n EUR: '€',\n GBP: '£',\n JPY: '¥',\n RUB: '₽',\n UAH: '₴',\n INR: '₹',\n AED: 'د.إ',\n};\n\nexport function getCurrencySign(currency: string | undefined): string {\n if (!currency) {\n return '';\n }\n return CURRENCIES[currency] || '';\n}\n","const VISA = /^4[0-9]{12}(?:[0-9]{1,3})?$/;\nconst MASTERCARD1 = /^5[1-5][0-9]{11,14}$/;\nconst MASTERCARD2 = /^2[2-7][0-9]{11,14}$/;\n\nexport enum CardType {\n Default,\n Visa,\n Mastercard,\n}\n\nconst cards: Record<number, string> = {\n [CardType.Default]: '',\n [CardType.Visa]: 'visa',\n [CardType.Mastercard]: 'mastercard',\n};\n\nexport function detectCardType(cardNumber: string): number {\n cardNumber = cardNumber.replace(/\\s/g, '');\n if (VISA.test(cardNumber)) {\n return CardType.Visa;\n }\n if (MASTERCARD1.test(cardNumber) || MASTERCARD2.test(cardNumber)) {\n return CardType.Mastercard;\n }\n return CardType.Default;\n}\n\nexport function detectCardTypeText(cardNumber: string): string {\n const cardType = detectCardType(cardNumber);\n return cards[cardType as number] || '';\n}\n","import useReducer, { StateReducer, Dispatch } from '../useReducer';\nimport { countryList } from '../../util/phoneNumber';\n\nexport type FormState = {\n streetLine1: string;\n streetLine2: string;\n city: string;\n state: string;\n countryIso2: string;\n postCode: string;\n fullName: string;\n email: string;\n phone: string;\n shipping: string;\n cardNumber: string;\n cardholder: string;\n expiry: string;\n cvv: string;\n billingCountry: string;\n billingZip: string;\n saveInfo: boolean;\n saveCredentials: boolean;\n formErrors: Record<string, string>;\n};\n\nexport type FormActions = (\n 'changeAddress1' | 'changeAddress2' | 'changeCity' | 'changeState' | 'changeCountry' |\n 'changePostCode' | 'changeFullName' | 'changeEmail' | 'changePhone' | 'changeShipping' | 'updateUserInfo' |\n 'changeCardNumber' | 'changeCardholder' | 'changeExpiryDate' | 'changeCvvCode' | 'changeBillingCountry' |\n 'changeBillingZip' | 'changeSaveInfo' | 'changeSaveCredentials' | 'setFormErrors'\n);\nexport type FormEditDispatch = Dispatch<FormActions>;\n\nconst INITIAL_STATE: FormState = {\n streetLine1: '',\n streetLine2: '',\n city: '',\n state: '',\n countryIso2: '',\n postCode: '',\n fullName: '',\n email: '',\n phone: '',\n shipping: '',\n cardNumber: '',\n cardholder: '',\n expiry: '',\n cvv: '',\n billingCountry: '',\n billingZip: '',\n saveInfo: true,\n saveCredentials: false,\n formErrors: {},\n};\n\nconst reducer: StateReducer<FormState, FormActions> = (state, action) => {\n switch (action.type) {\n case 'changeAddress1':\n return {\n ...state,\n streetLine1: action.payload,\n formErrors: {\n ...state.formErrors,\n streetLine1: undefined,\n },\n };\n case 'changeAddress2':\n return {\n ...state,\n streetLine2: action.payload,\n formErrors: {\n ...state.formErrors,\n streetLine2: undefined,\n },\n };\n case 'changeCity':\n return {\n ...state,\n city: action.payload,\n formErrors: {\n ...state.formErrors,\n city: undefined,\n },\n };\n case 'changeState':\n return {\n ...state,\n state: action.payload,\n formErrors: {\n ...state.formErrors,\n state: undefined,\n },\n };\n case 'changeCountry':\n return {\n ...state,\n countryIso2: action.payload,\n billingCountry: getBillingCountry(action.payload),\n formErrors: {\n ...state.formErrors,\n countryIso2: undefined,\n },\n };\n case 'changePostCode':\n return {\n ...state,\n postCode: action.payload,\n formErrors: {\n ...state.formErrors,\n postCode: undefined,\n },\n };\n case 'changeFullName':\n return {\n ...state,\n fullName: action.payload,\n formErrors: {\n ...state.formErrors,\n fullName: undefined,\n },\n };\n case 'changeEmail':\n return {\n ...state,\n email: action.payload,\n formErrors: {\n ...state.formErrors,\n email: undefined,\n },\n };\n case 'changePhone':\n return {\n ...state,\n phone: action.payload,\n formErrors: {\n ...state.formErrors,\n phone: undefined,\n },\n };\n case 'changeShipping':\n return { ...state, shipping: action.payload };\n case 'changeCardNumber':\n return {\n ...state,\n cardNumber: action.payload,\n formErrors: {\n ...state.formErrors,\n cardNumber: undefined,\n },\n };\n case 'changeCardholder':\n return {\n ...state,\n cardholder: action.payload,\n formErrors: {\n ...state.formErrors,\n cardholder: undefined,\n },\n };\n case 'changeExpiryDate':\n return {\n ...state,\n expiry: action.payload,\n formErrors: {\n ...state.formErrors,\n expiry: undefined,\n },\n };\n case 'changeCvvCode':\n return {\n ...state,\n cvv: action.payload,\n formErrors: {\n ...state.formErrors,\n cvv: undefined,\n },\n };\n case 'changeBillingCountry':\n return {\n ...state,\n billingCountry: action.payload,\n formErrors: {\n ...state.formErrors,\n billingCountry: undefined,\n },\n };\n case 'changeBillingZip':\n return {\n ...state,\n billingZip: action.payload,\n formErrors: {\n ...state.formErrors,\n billingZip: undefined,\n },\n };\n case 'changeSaveInfo':\n return { ...state, saveInfo: action.payload };\n case 'changeSaveCredentials':\n return { ...state, saveCredentials: action.payload };\n case 'updateUserInfo':\n if (action.payload.countryIso2) {\n return {\n ...state,\n ...action.payload,\n billingCountry: getBillingCountry(action.payload.countryIso2),\n };\n }\n return { ...state, ...action.payload };\n case 'setFormErrors':\n return {\n ...state,\n formErrors: {\n ...state.formErrors,\n ...action.payload,\n },\n };\n default:\n return state;\n }\n};\n\nfunction getBillingCountry(countryCode: string) {\n const country = countryList.find(({ id }) => id === countryCode);\n return country ? country.name : '';\n}\n\nexport default () => {\n return useReducer(reducer, INITIAL_STATE);\n};\n","import { RefObject } from 'react';\n\nimport { IS_TOUCH_ENV } from '../util/environment';\nimport { fastRaf } from '../util/schedulers';\nimport { useEffect } from '../lib/teact/teact';\n\nconst DEFAULT_DURATION = 400;\n\nexport default function useFocusAfterAnimation(\n ref: RefObject<HTMLInputElement>, animationDuration = DEFAULT_DURATION,\n) {\n useEffect(() => {\n if (IS_TOUCH_ENV) {\n return;\n }\n\n setTimeout(() => {\n fastRaf(() => {\n if (ref.current) {\n ref.current.focus();\n }\n });\n }, animationDuration);\n }, [ref, animationDuration]);\n}\n","import { ChangeEvent, RefObject } from 'react';\nimport React, { FC, memo } from '../../lib/teact/teact';\n\n\nimport buildClassName from '../../util/buildClassName';\n\ntype OwnProps = {\n id?: string;\n value?: string;\n label?: string;\n error?: string;\n ref?: RefObject<HTMLSelectElement>;\n hasArrow?: boolean;\n placeholder?: string;\n onChange?: (e: ChangeEvent<HTMLSelectElement>) => void;\n children: any;\n};\n\nconst Select: FC<OwnProps> = (props) => {\n const {\n id,\n value,\n label,\n hasArrow,\n error,\n ref,\n placeholder,\n onChange,\n children,\n } = props;\n const labelText = error || label;\n const fullClassName = buildClassName(\n 'input-group',\n value && 'touched',\n error && 'error',\n labelText && 'with-label',\n hasArrow && 'with-arrow',\n 'input-group',\n );\n\n return (\n <div className={fullClassName}>\n <select\n className=\"form-control\"\n id={id}\n value={value || ''}\n onChange={onChange}\n placeholder={placeholder || label}\n ref={ref}\n >\n {children}\n </select>\n {labelText && id && (\n <label htmlFor={id}>{labelText}</label>\n )}\n </div>\n );\n};\n\nexport default memo(Select);\n","import React, {\n FC, useRef, useCallback, useEffect, memo,\n} from '../../lib/teact/teact';\n\nimport { FormState, FormEditDispatch } from '../../hooks/reducers/usePaymentReducer';\nimport useFocusAfterAnimation from '../../hooks/useFocusAfterAnimation';\nimport useLang from '../../hooks/useLang';\nimport { countryList } from '../../util/phoneNumber';\n\nimport InputText from '../ui/InputText';\nimport Select from '../ui/Select';\nimport Checkbox from '../ui/Checkbox';\n\nimport './ShippingInfo.scss';\n\nexport type OwnProps = {\n state: FormState;\n needEmail: boolean;\n needPhone: boolean;\n needName: boolean;\n needAddress: boolean;\n dispatch: FormEditDispatch;\n};\n\nconst ShippingInfo: FC<OwnProps> = ({\n state,\n needEmail,\n needPhone,\n needName,\n needAddress,\n dispatch,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n // eslint-disable-next-line no-null/no-null\n const phoneRef = useRef<HTMLInputElement>(null);\n // eslint-disable-next-line no-null/no-null\n const selectCountryRef = useRef<HTMLSelectElement>(null);\n\n useEffect(() => {\n if (selectCountryRef.current\n && selectCountryRef.current.value !== state.countryIso2) {\n selectCountryRef.current.value = state.countryIso2;\n }\n }, [state.countryIso2]);\n\n const lang = useLang();\n\n useFocusAfterAnimation(inputRef);\n\n const handleAddress1Change = useCallback((e) => {\n dispatch({ type: 'changeAddress1', payload: e.target.value });\n }, [dispatch]);\n\n const handleAddress2Change = useCallback((e) => {\n dispatch({ type: 'changeAddress2', payload: e.target.value });\n }, [dispatch]);\n\n const handleCityChange = useCallback((e) => {\n dispatch({ type: 'changeCity', payload: e.target.value });\n }, [dispatch]);\n\n const handleStateChange = useCallback((e) => {\n dispatch({ type: 'changeState', payload: e.target.value });\n }, [dispatch]);\n\n const handleCountryChange = useCallback((e) => {\n dispatch({ type: 'changeCountry', payload: e.target.value });\n }, [dispatch]);\n\n const handlePostCodeChange = useCallback((e) => {\n dispatch({ type: 'changePostCode', payload: e.target.value });\n }, [dispatch]);\n\n const handleFullNameChange = useCallback((e) => {\n dispatch({ type: 'changeFullName', payload: e.target.value });\n }, [dispatch]);\n\n const handleEmailChange = useCallback((e) => {\n dispatch({ type: 'changeEmail', payload: e.target.value });\n }, [dispatch]);\n\n const handlePhoneChange = useCallback((e) => {\n let { value } = e.target;\n value = `+${value.replace(/\\D/g, '')}`;\n if (phoneRef.current) {\n phoneRef.current.value = value;\n }\n dispatch({ type: 'changePhone', payload: value });\n }, [dispatch]);\n\n const handleSaveInfoChange = useCallback((e) => {\n dispatch({ type: 'changeSaveInfo', payload: e.target.value });\n }, [dispatch]);\n\n const { formErrors } = state;\n return (\n <div className=\"ShippingInfo\">\n <form>\n {needAddress ? (\n <div>\n <h5>{lang('PaymentShippingAddress')}</h5>\n <InputText\n ref={inputRef}\n label=\"Address1 (Street)\"\n onChange={handleAddress1Change}\n value={state.streetLine1}\n inputMode=\"text\"\n error={formErrors.streetLine1}\n />\n <InputText\n label=\"Address2 (Street)\"\n onChange={handleAddress2Change}\n value={state.streetLine2}\n inputMode=\"text\"\n error={formErrors.streetLine2}\n />\n <InputText\n label=\"City\"\n onChange={handleCityChange}\n value={state.city}\n inputMode=\"text\"\n error={formErrors.city}\n />\n <InputText\n label=\"State\"\n onChange={handleStateChange}\n value={state.state}\n inputMode=\"text\"\n error={formErrors.state}\n />\n <Select\n label=\"Country\"\n placeholder=\"Country\"\n onChange={handleCountryChange}\n value={state.countryIso2}\n hasArrow={Boolean(true)}\n id=\"shipping-country\"\n error={formErrors.countryIso2}\n ref={selectCountryRef}\n >\n {countryList.map(({ name, id }) => (\n <option\n value={id}\n className=\"county-item\"\n >\n {name}\n </option>\n ))}\n </Select>\n\n <InputText\n label=\"Post Code\"\n onChange={handlePostCodeChange}\n value={state.postCode}\n inputMode=\"text\"\n error={formErrors.postCode}\n />\n </div>\n ) : undefined}\n { needName || needEmail || needPhone ? (\n <h5>{lang('PaymentShippingReceiver')}</h5>\n ) : undefined }\n { needName && (\n <InputText\n label=\"Full name\"\n onChange={handleFullNameChange}\n value={state.fullName}\n inputMode=\"text\"\n error={formErrors.fullName}\n />\n ) }\n { needEmail && (\n <InputText\n label=\"Email\"\n onChange={handleEmailChange}\n value={state.email}\n inputMode=\"email\"\n error={formErrors.email}\n />\n ) }\n { needPhone && (\n <InputText\n label=\"Phone number\"\n onChange={handlePhoneChange}\n value={state.phone}\n inputMode=\"tel\"\n error={formErrors.phone}\n ref={phoneRef}\n />\n ) }\n <Checkbox\n label={lang('PaymentShippingSave')}\n subLabel={lang('PaymentShippingSaveInfo')}\n checked={Boolean(state.saveInfo)}\n onChange={handleSaveInfoChange}\n />\n </form>\n </div>\n );\n};\n\nexport default memo(ShippingInfo);\n","import React, {\n FC, useCallback, memo, useMemo, useEffect,\n} from '../../lib/teact/teact';\n\nimport { ShippingOption } from '../../types/index';\n\nimport { FormState, FormEditDispatch } from '../../hooks/reducers/usePaymentReducer';\n\nimport RadioGroup from '../ui/RadioGroup';\n\nimport './Shipping.scss';\n\nexport type OwnProps = {\n state: FormState;\n shippingOptions: ShippingOption[];\n currency: string;\n dispatch: FormEditDispatch;\n};\n\nconst Shipping: FC<OwnProps> = ({\n state,\n shippingOptions,\n currency,\n dispatch,\n}) => {\n useEffect(() => {\n if (!shippingOptions || state.shipping) {\n return;\n }\n dispatch({ type: 'changeShipping', payload: shippingOptions[0].id });\n }, [shippingOptions, state.shipping, dispatch]);\n\n const handleShippingSelect = useCallback((value) => {\n dispatch({ type: 'changeShipping', payload: value });\n }, [dispatch]);\n\n const options = useMemo(() => (shippingOptions.map(({ id: value, title: label, amount }) => ({\n label,\n subLabel: `${currency} ${String(amount / 100)}`,\n value,\n }))), [shippingOptions, currency]);\n\n return (\n <div className=\"Shipping\">\n <form>\n <p>Select shipping method</p>\n <RadioGroup\n name=\"shipping-options\"\n options={options}\n onChange={handleShippingSelect}\n selected={state.shipping}\n />\n </form>\n </div>\n );\n};\n\nexport default memo(Shipping);\n","import React, {\n FC, memo,\n} from '../../lib/teact/teact';\n\nimport { Price } from '../../types';\n\nimport './Checkout.scss';\n\nexport type OwnProps = {\n invoiceContent?: {\n title?: string;\n description?: string;\n text?: string;\n photoUrl?: string;\n };\n checkoutInfo?: {\n paymentMethod?: string;\n paymentProvider?: string;\n shippingAddress?: string;\n name?: string;\n phone?: string;\n shippingMethod?: string;\n };\n prices?: Price[];\n totalPrice?: number;\n shippingPrices?: Price[];\n currency?: string;\n};\n\nconst Checkout: FC<OwnProps> = ({\n invoiceContent,\n prices,\n shippingPrices,\n checkoutInfo,\n currency,\n totalPrice,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const { photoUrl, title, text } = (invoiceContent || {});\n const {\n paymentMethod,\n paymentProvider,\n shippingAddress,\n name,\n phone,\n shippingMethod,\n } = (checkoutInfo || {});\n return (\n <div className=\"Checkout\">\n <div className=\"description has-image\">\n { photoUrl && (\n <img src={photoUrl} alt=\"\" />\n )}\n <div className=\"text\">\n <h5>{ title }</h5>\n <p>{ text }</p>\n </div>\n </div>\n <div className=\"price-info\">\n { prices && prices.map((item) => (\n renderPaymentItem(item.label, item.amount, currency, false)\n )) }\n { shippingPrices && shippingPrices.map((item) => (\n renderPaymentItem(item.label, item.amount, currency, false)\n )) }\n { totalPrice !== undefined && (\n renderPaymentItem('Total', totalPrice, currency, true)\n ) }\n </div>\n <div className=\"invoice-info\">\n {paymentMethod && renderCheckoutItem('icon-card', paymentMethod, 'Payment method')}\n {paymentProvider && renderCheckoutItem('stripe-provider', paymentProvider, 'Payment provider')}\n {shippingAddress && renderCheckoutItem('icon-location', shippingAddress, 'Shipping address')}\n {name && renderCheckoutItem('icon-user', name, 'Name')}\n {phone && renderCheckoutItem('icon-phone', phone, 'Phone number')}\n {shippingMethod && renderCheckoutItem('icon-truck', shippingMethod, 'Shipping method')}\n </div>\n </div>\n );\n};\n\nfunction renderPaymentItem(title: string, value: number, currency?: string, main = false) {\n return (\n <div className={`price-info-item ${main ? 'price-info-item-main' : ''}`}>\n <div className=\"title\">\n { title }\n </div>\n <div className=\"value\">\n { `${currency || ''} ${(value / 100).toFixed(2)}` }\n </div>\n </div>\n );\n}\n\nfunction renderCheckoutItem(icon: string, title: string, data: string) {\n return (\n <div className=\"checkout-info-item\">\n <i className={icon}> </i>\n <div className=\"info\">\n <div className=\"title\">\n { title }\n </div>\n <p className=\"data\">\n { data }\n </p>\n </div>\n </div>\n );\n}\n\nexport default memo(Checkout);\n","import React, {\n FC, memo, useCallback, useRef,\n} from '../../lib/teact/teact';\n\nimport { formatCardExpiry } from '../middle/helpers/inputFormatters';\n\nimport InputText from '../ui/InputText';\n\nconst MAX_FIELD_LENGTH = 5;\n\nexport type OwnProps = {\n value: string;\n error?: string;\n onChange: (value: string) => void;\n};\n\nconst ExpiryInput : FC<OwnProps> = ({ value, error, onChange }) => {\n // eslint-disable-next-line no-null/no-null\n const expiryInputRef = useRef<HTMLInputElement>(null);\n\n const handleKeyDown = useCallback((e) => {\n if (e.key === 'Backspace' && value.charAt(value.length - 1) === '/') {\n const newValue = value.slice(0, value.length - 1);\n if (expiryInputRef.current) {\n expiryInputRef.current.value = newValue;\n }\n }\n }, [value]);\n\n const handleChange = useCallback((e) => {\n onChange(formatCardExpiry(e.target.value));\n }, [onChange]);\n\n return (\n <InputText\n label=\"Expiry date\"\n ref={expiryInputRef}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n value={value}\n error={error}\n inputMode=\"numeric\"\n maxLength={MAX_FIELD_LENGTH}\n />\n );\n};\n\nexport default memo(ExpiryInput);\n","export function formatCardExpiry(input: string) {\n input = input.replace(/[^\\d]/g, '').slice(0, 4);\n const parts = input.match(/.{1,2}/g);\n if (parts && parts[0] && Number(parts[0]) > 12) {\n parts[0] = '12';\n }\n if (parts && parts[0] && parts[0].length === 2 && !parts[1]) {\n parts[1] = '';\n }\n return parts ? parts.join('/') : '';\n}\n\nexport function formatCardNumber(input: string) {\n input = input.replace(/[^\\d]/g, '');\n const parts = input.match(/.{1,4}/g);\n return parts ? parts.join(' ') : '';\n}\n","export default __webpack_public_path__ + \"mastercard.4216118edafe23cc2dec7b8807ba4622.svg\";","export default __webpack_public_path__ + \"visa.e5a7c336e1deb4b92a636e2e053878c4.svg\";","import React, {\n FC, memo, useCallback, useState, useRef, useEffect,\n} from '../../lib/teact/teact';\n\nimport useFocusAfterAnimation from '../../hooks/useFocusAfterAnimation';\nimport { formatCardNumber } from '../middle/helpers/inputFormatters';\nimport { detectCardType, CardType } from '../common/helpers/detectCardType';\n\nimport InputText from '../ui/InputText';\n\nimport './CardInput.scss';\n\n// @ts-ignore\nimport mastercardIconPath from '../../assets/mastercard.svg';\n// @ts-ignore\nimport visaIconPath from '../../assets/visa.svg';\n\nconst CARD_NUMBER_MAX_LENGTH = 23;\n\nexport type OwnProps = {\n value: string;\n error?: string;\n onChange: (value: string) => void;\n};\n\nconst CardInput : FC<OwnProps> = ({ value, error, onChange }) => {\n // eslint-disable-next-line no-null/no-null\n const cardNumberRef = useRef<HTMLInputElement>(null);\n\n useFocusAfterAnimation(cardNumberRef);\n\n const [cardType, setCardType] = useState<number>(CardType.Default);\n useEffect(() => {\n const newCardType = detectCardType(value);\n setCardType(newCardType);\n // eslint-disable-next-line\n }, []);\n\n const handleChange = useCallback((e) => {\n const newValue = formatCardNumber(e.target.value);\n const newCardType = detectCardType(e.target.value);\n setCardType(newCardType);\n onChange(newValue);\n if (cardNumberRef.current) {\n cardNumberRef.current.value = newValue;\n }\n }, [onChange, cardNumberRef]);\n\n const cardIcon = getCardIcon(cardType);\n\n return (\n <div className=\"CardInput\">\n <span className=\"left-addon\">{cardIcon}</span>\n <InputText\n ref={cardNumberRef}\n label=\"Card number\"\n onChange={handleChange}\n value={value}\n inputMode=\"numeric\"\n className={cardType ? 'has-left-addon' : ''}\n error={error}\n maxLength={CARD_NUMBER_MAX_LENGTH}\n />\n </div>\n );\n};\n\nexport default memo(CardInput);\n\nfunction getCardIcon(cardType: CardType) {\n switch (cardType) {\n case CardType.Mastercard:\n return <img src={mastercardIconPath} alt=\"\" />;\n case CardType.Visa:\n return <img src={visaIconPath} alt=\"\" />;\n default:\n return undefined;\n }\n}\n","import React, {\n FC, useCallback, memo, useRef, useEffect,\n} from '../../lib/teact/teact';\n\nimport { FormState, FormEditDispatch } from '../../hooks/reducers/usePaymentReducer';\nimport useLang from '../../hooks/useLang';\nimport { countryList } from '../../util/phoneNumber';\n\nimport InputText from '../ui/InputText';\nimport Checkbox from '../ui/Checkbox';\nimport Select from '../ui/Select';\nimport ExpiryInput from './ExpiryInput';\nimport CardInput from './CardInput';\n\nimport './PaymentInfo.scss';\n\nexport type OwnProps = {\n state: FormState;\n canSaveCredentials: boolean;\n needCardholderName?: boolean;\n needCountry?: boolean;\n needZip?: boolean;\n dispatch: FormEditDispatch;\n};\n\nconst PaymentInfo: FC<OwnProps> = ({\n state,\n canSaveCredentials,\n needCardholderName,\n needCountry,\n needZip,\n dispatch,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const selectCountryRef = useRef<HTMLSelectElement>(null);\n\n useEffect(() => {\n if (selectCountryRef.current\n && selectCountryRef.current.value !== state.billingCountry) {\n selectCountryRef.current.value = state.billingCountry;\n }\n }, [state.billingCountry]);\n\n const handleCardNumberChange = useCallback((value) => {\n dispatch({ type: 'changeCardNumber', payload: value });\n }, [dispatch]);\n\n const handleCardholderChange = useCallback((e) => {\n dispatch({ type: 'changeCardholder', payload: e.target.value.toUpperCase() });\n }, [dispatch]);\n\n const handleExpiryChange = useCallback((value) => {\n dispatch({ type: 'changeExpiryDate', payload: value });\n }, [dispatch]);\n\n const handleCvvChange = useCallback((e) => {\n dispatch({ type: 'changeCvvCode', payload: e.target.value });\n }, [dispatch]);\n\n const handleCountryChange = useCallback((e) => {\n dispatch({ type: 'changeBillingCountry', payload: e.target.value });\n }, [dispatch]);\n\n const handleBillingPostCodeChange = useCallback((e) => {\n dispatch({ type: 'changeBillingZip', payload: e.target.value });\n }, [dispatch]);\n\n const handleChangeSaveCredentials = useCallback((e) => {\n dispatch({ type: 'changeSaveCredentials', payload: e.target.value });\n }, [dispatch]);\n\n const lang = useLang();\n\n const { formErrors = {} } = state;\n\n return (\n <div className=\"PaymentInfo\">\n <form>\n <h5>{lang('PaymentCardTitle')}</h5>\n <CardInput\n onChange={handleCardNumberChange}\n value={state.cardNumber}\n error={formErrors.cardNumber}\n />\n { needCardholderName && (\n <InputText\n label=\"Name on card\"\n onChange={handleCardholderChange}\n value={state.cardholder}\n inputMode=\"text\"\n error={formErrors.cardholder}\n />\n )}\n <section className=\"inline-inputs\">\n <ExpiryInput\n value={state.expiry}\n onChange={handleExpiryChange}\n error={formErrors.expiry}\n />\n <InputText\n label=\"CVV code\"\n onChange={handleCvvChange}\n value={state.cvv}\n inputMode=\"numeric\"\n maxLength={3}\n error={formErrors.cvv}\n />\n </section>\n { needCountry || needZip ? (\n <h5>{lang('PaymentBillingAddress')}</h5>\n ) : undefined }\n { needCountry && (\n <Select\n label=\"Country\"\n placeholder=\"Country\"\n onChange={handleCountryChange}\n value={state.billingCountry}\n hasArrow={Boolean(true)}\n id=\"billing-country\"\n error={formErrors.billingCountry}\n ref={selectCountryRef}\n >\n {\n countryList.map(({ name }) => (\n <option\n value={name}\n className=\"county-item\"\n >\n {name}\n </option>\n ))\n }\n </Select>\n ) }\n { needZip && (\n <InputText\n label=\"Post Code\"\n onChange={handleBillingPostCodeChange}\n value={state.billingZip}\n inputMode=\"text\"\n error={formErrors.billingZip}\n />\n )}\n { canSaveCredentials && (\n <Checkbox\n label={lang('PaymentCardSavePaymentInformation')}\n checked={state.saveCredentials}\n onChange={handleChangeSaveCredentials}\n />\n ) }\n </form>\n </div>\n );\n};\n\nexport default memo(PaymentInfo);\n","import React, {\n FC, memo, useCallback, useEffect, useMemo, useState,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { GlobalActions, GlobalState } from '../../global/types';\nimport { PaymentStep, ShippingOption, Price } from '../../types';\nimport { ApiError } from '../../api/types';\n\nimport { pick } from '../../util/iteratees';\nimport { getCurrencySign } from '../middle/helpers/getCurrencySign';\nimport { detectCardTypeText } from '../common/helpers/detectCardType';\nimport { getShippingError } from '../../modules/helpers/payments';\nimport usePaymentReducer, { FormState } from '../../hooks/reducers/usePaymentReducer';\nimport useLang from '../../hooks/useLang';\n\nimport ShippingInfo from './ShippingInfo';\nimport Shipping from './Shipping';\nimport Checkout from './Checkout';\nimport PaymentInfo from './PaymentInfo';\nimport Button from '../ui/Button';\nimport Modal from '../ui/Modal';\nimport Transition from '../ui/Transition';\nimport Spinner from '../ui/Spinner';\n\nimport './PaymentModal.scss';\n\nconst DEFAULT_PROVIDER = 'stripe';\n\nexport type OwnProps = {\n isOpen: boolean;\n onClose: () => void;\n};\n\ntype StateProps = {\n nameRequested?: boolean;\n shippingAddressRequested?: boolean;\n phoneRequested?: boolean;\n emailRequested?: boolean;\n flexible?: boolean;\n phoneToProvider?: boolean;\n emailToProvider?: boolean;\n currency?: string;\n prices?: Price[];\n isProviderError: boolean;\n needCardholderName?: boolean;\n needCountry?: boolean;\n needZip?: boolean;\n globalErrors?: ApiError[];\n};\n\ntype GlobalStateProps = Pick<GlobalState['payment'], 'step' | 'shippingOptions' |\n'savedInfo' | 'canSaveCredentials' | 'nativeProvider' | 'passwordMissing' | 'invoiceContent' |\n'error'>;\n\ntype DispatchProps = Pick<GlobalActions, 'validateRequestedInfo' | 'sendPaymentForm' | 'setPaymentStep'\n| 'sendCredentialsInfo' | 'clearPaymentError' >;\n\nconst Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({\n isOpen,\n onClose,\n step,\n shippingOptions,\n savedInfo,\n canSaveCredentials,\n nameRequested,\n shippingAddressRequested,\n phoneRequested,\n emailRequested,\n phoneToProvider,\n emailToProvider,\n currency,\n passwordMissing,\n isProviderError,\n invoiceContent,\n nativeProvider,\n prices,\n needCardholderName,\n needCountry,\n needZip,\n error,\n globalErrors,\n validateRequestedInfo,\n sendPaymentForm,\n setPaymentStep,\n sendCredentialsInfo,\n clearPaymentError,\n}) => {\n const [paymentState, paymentDispatch] = usePaymentReducer();\n const currencySign = getCurrencySign(currency);\n const [isLoading, setIsLoading] = useState(false);\n const lang = useLang();\n\n useEffect(() => {\n if (step || error || globalErrors) {\n setIsLoading(false);\n }\n }, [step, error, globalErrors]);\n\n useEffect(() => {\n if (error && error.field) {\n paymentDispatch({\n type: 'setFormErrors',\n payload: {\n [error.field]: error.fieldError,\n },\n });\n return;\n }\n if (globalErrors && globalErrors.length) {\n const errors = getShippingError(globalErrors);\n paymentDispatch({\n type: 'setFormErrors',\n payload: {\n ...errors,\n },\n });\n }\n }, [error, globalErrors, paymentDispatch]);\n\n useEffect(() => {\n if (savedInfo) {\n const {\n name: fullName, phone, email, shippingAddress,\n } = savedInfo;\n paymentDispatch({\n type: 'updateUserInfo',\n payload: {\n fullName,\n phone: phone && phone.charAt(0) !== '+'\n ? `+${phone}`\n : phone,\n email,\n ...(shippingAddress || {}),\n },\n });\n }\n }, [savedInfo, paymentDispatch]);\n\n const handleErrorModalClose = useCallback(() => {\n clearPaymentError();\n }, [clearPaymentError]);\n\n const totalPrice = useMemo(() => {\n if (step !== PaymentStep.Checkout) {\n return 0;\n }\n\n return getTotalPrice(prices, shippingOptions, paymentState.shipping);\n }, [step, paymentState.shipping, prices, shippingOptions]);\n\n const checkoutInfo = useMemo(() => {\n if (step !== PaymentStep.Checkout) {\n return undefined;\n }\n return getCheckoutInfo(paymentState, shippingOptions, nativeProvider || '');\n }, [step, paymentState, shippingOptions, nativeProvider]);\n\n function renderError() {\n if (!error) {\n return undefined;\n }\n return (\n <Modal\n className=\"error\"\n isOpen={Boolean(error)}\n onClose={handleErrorModalClose}\n >\n <h4>{error.description || 'Error'}</h4>\n {error.description || 'Error'}\n <Button\n isText\n onClick={clearPaymentError}\n >\n OK\n </Button>\n </Modal>\n );\n }\n\n function renderModalContent(cuurentStep: PaymentStep) {\n switch (cuurentStep) {\n case PaymentStep.ShippingInfo:\n return (\n <ShippingInfo\n state={paymentState}\n dispatch={paymentDispatch}\n needAddress={Boolean(shippingAddressRequested)}\n needEmail={Boolean(emailRequested || emailToProvider)}\n needPhone={Boolean(phoneRequested || phoneToProvider)}\n needName={Boolean(nameRequested)}\n />\n );\n case PaymentStep.Shipping:\n return (\n <Shipping\n state={paymentState}\n dispatch={paymentDispatch}\n shippingOptions={shippingOptions || []}\n currency={currencySign}\n />\n );\n case PaymentStep.PaymentInfo:\n return (\n <PaymentInfo\n state={paymentState}\n dispatch={paymentDispatch}\n canSaveCredentials={Boolean(!passwordMissing && canSaveCredentials)}\n needCardholderName={needCardholderName}\n needCountry={needCountry}\n needZip={needZip}\n />\n );\n case PaymentStep.Checkout:\n return (\n <Checkout\n prices={prices}\n shippingPrices={paymentState.shipping && shippingOptions\n ? getShippingPrices(shippingOptions, paymentState.shipping)\n : undefined}\n totalPrice={totalPrice}\n invoiceContent={invoiceContent}\n checkoutInfo={checkoutInfo}\n currency={currencySign}\n />\n );\n default:\n return undefined;\n }\n }\n\n const validateRequest = useCallback(() => {\n const { saveInfo } = paymentState;\n const requestInfo = getRequestInfo(paymentState);\n validateRequestedInfo({ requestInfo, saveInfo });\n }, [validateRequestedInfo, paymentState]);\n\n const sendCredentials = useCallback(() => {\n const credentials = getCredentials(paymentState);\n sendCredentialsInfo({\n credentials,\n });\n }, [sendCredentialsInfo, paymentState]);\n\n const sendForm = useCallback(() => {\n sendPaymentForm({\n shippingOptionId: paymentState.shipping,\n saveCredentials: paymentState.saveCredentials,\n });\n }, [sendPaymentForm, paymentState]);\n\n const setStep = useCallback((nextStep) => {\n setPaymentStep({ step: nextStep });\n }, [setPaymentStep]);\n\n const handleButtonClick = useCallback(() => {\n setIsLoading(true);\n switch (step) {\n case PaymentStep.ShippingInfo:\n return validateRequest();\n case PaymentStep.Shipping:\n return setStep(PaymentStep.PaymentInfo);\n case PaymentStep.PaymentInfo:\n return sendCredentials();\n case PaymentStep.Checkout:\n return sendForm();\n default:\n return () => {};\n }\n }, [step, validateRequest, setStep, sendCredentials, sendForm]);\n\n const modalHeader = useMemo(() => {\n switch (step) {\n case PaymentStep.ShippingInfo:\n return lang('PaymentShippingInfo');\n case PaymentStep.Shipping:\n return lang('PaymentShippingMethod');\n case PaymentStep.PaymentInfo:\n return lang('PaymentCardInfo');\n case PaymentStep.Checkout:\n return lang('PaymentCheckout');\n default:\n return '';\n }\n }, [step, lang]);\n\n const buttonText = useMemo(() => {\n switch (step) {\n case PaymentStep.Checkout:\n return `Pay ${currencySign}${(totalPrice / 100).toFixed(2)}`;\n default:\n return 'Next Step';\n }\n }, [step, totalPrice, currencySign]);\n\n if (isProviderError) {\n return (\n <Modal\n className=\"error\"\n isOpen={isOpen}\n onClose={onClose}\n >\n Sorry, Telegram T doesn't support payments with this provider yet.\n Please use one of our mobile apps to do this.\n <Button\n isText\n onClick={onClose}\n >\n OK\n </Button>\n </Modal>\n );\n }\n\n return (\n <Modal\n className=\"PaymentModal\"\n isOpen={isOpen}\n onClose={onClose}\n >\n <div className=\"header\">\n <Button\n className=\"close-button\"\n color=\"translucent\"\n round\n size=\"smaller\"\n onClick={onClose}\n ariaLabel=\"Close\"\n >\n <i className=\"icon-close\" />\n </Button>\n <h3>{ modalHeader }</h3>\n </div>\n {step !== undefined ? (\n <Transition name=\"slide\" activeKey={step}>\n {() => (\n <div className=\"content custom-scroll\">\n {renderModalContent(step)}\n </div>\n )}\n </Transition>\n ) : (\n <div className=\"empty-content\">\n <Spinner color=\"gray\" />\n </div>\n )}\n <div className=\"footer\">\n <Button\n type=\"submit\"\n onClick={handleButtonClick}\n disabled={isLoading}\n isLoading={isLoading}\n >\n {buttonText}\n </Button>\n </div>\n {error && !error.field && renderError()}\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps & GlobalStateProps => {\n const {\n step,\n shippingOptions,\n savedInfo,\n canSaveCredentials,\n invoice,\n invoiceContent,\n nativeProvider,\n nativeParams,\n passwordMissing,\n error,\n } = global.payment;\n\n const isProviderError = Boolean(invoice && (!nativeProvider || nativeProvider !== DEFAULT_PROVIDER));\n const { needCardholderName, needCountry, needZip } = (nativeParams || {});\n const {\n nameRequested,\n phoneRequested,\n emailRequested,\n shippingAddressRequested,\n flexible,\n phoneToProvider,\n emailToProvider,\n currency,\n prices,\n } = (invoice || {});\n\n return {\n step,\n shippingOptions,\n savedInfo,\n canSaveCredentials,\n nativeProvider,\n passwordMissing,\n nameRequested,\n shippingAddressRequested,\n phoneRequested,\n emailRequested,\n flexible,\n phoneToProvider,\n emailToProvider,\n currency,\n prices,\n isProviderError,\n invoiceContent,\n needCardholderName,\n needCountry,\n needZip,\n error,\n globalErrors: global.errors,\n };\n },\n (setGlobal, actions): DispatchProps => {\n return pick(actions, [\n 'validateRequestedInfo',\n 'sendPaymentForm',\n 'setPaymentStep',\n 'sendCredentialsInfo',\n 'clearPaymentError',\n ]);\n },\n)(Invoice));\n\nfunction findShippingOption(shippingOptions: ShippingOption[], optionId: string) {\n return shippingOptions.find(({ id }) => id === optionId);\n}\n\nfunction getShippingPrices(shippingOptions: ShippingOption[], shippingOption: string) {\n const option = findShippingOption(shippingOptions, shippingOption);\n return option ? option.prices : undefined;\n}\n\nfunction getTotalPrice(prices: Price[] = [], shippingOptions: ShippingOption[] | undefined, shippingOption: string) {\n const shippingPrices = shippingOptions\n ? getShippingPrices(shippingOptions, shippingOption)\n : [];\n let total = 0;\n const totalPrices = prices.concat(shippingPrices || []);\n total = totalPrices.reduce((acc, cur) => {\n return acc + cur.amount;\n }, total);\n return total;\n}\n\nfunction getCheckoutInfo(state: FormState, shippingOptions: ShippingOption[] | undefined, paymentProvider: string) {\n const cardTypeText = detectCardTypeText(state.cardNumber);\n const paymentMethod = `${cardTypeText} *${state.cardNumber.slice(-4)}`;\n const shippingAddress = state.streetLine1\n ? `${state.streetLine1}, ${state.city}, ${state.countryIso2}`\n : undefined;\n const { phone, fullName: name } = state;\n const shippingOption = shippingOptions ? findShippingOption(shippingOptions, state.shipping) : undefined;\n const shippingMethod = shippingOption ? shippingOption.title : undefined;\n return {\n paymentMethod,\n paymentProvider,\n shippingAddress,\n name,\n phone,\n shippingMethod,\n };\n}\n\nfunction getRequestInfo(paymentState: FormState) {\n const {\n streetLine1,\n streetLine2,\n city,\n state,\n countryIso2,\n postCode,\n fullName: name,\n phone,\n email,\n } = paymentState;\n\n const shippingAddress = {\n streetLine1,\n streetLine2,\n city,\n state,\n countryIso2,\n postCode,\n };\n\n return {\n name,\n phone,\n email,\n shippingAddress,\n };\n}\n\nfunction getCredentials(paymentState: FormState) {\n const {\n cardNumber, cardholder, expiry, cvv, billingCountry, billingZip,\n } = paymentState;\n const [expiryMonth, expiryYear] = expiry.split('/');\n const data = {\n cardNumber,\n cardholder,\n expiryMonth,\n expiryYear,\n cvv,\n country: billingCountry,\n zip: billingZip,\n };\n\n return {\n data,\n };\n}\n","import React, {\n FC, memo, useMemo,\n} from '../../lib/teact/teact';\nimport { withGlobal } from '../../lib/teact/teactn';\n\nimport { Price } from '../../types';\nimport { ApiShippingAddress } from '../../api/types/payments';\n\nimport useLang from '../../hooks/useLang';\nimport { getCurrencySign } from '../middle/helpers/getCurrencySign';\n\nimport Checkout from './Checkout';\nimport Modal from '../ui/Modal';\nimport Button from '../ui/Button';\n\nimport './PaymentModal.scss';\n\nexport type OwnProps = {\n isOpen: boolean;\n onClose: () => void;\n};\n\ntype StateProps = {\n prices?: Price[];\n shippingPrices: any;\n totalAmount?: number;\n currency?: string;\n info?: {\n shippingAddress?: ApiShippingAddress;\n phone?: string;\n name?: string;\n };\n photoUrl?: string;\n text?: string;\n title?: string;\n credentialsTitle?: string;\n shippingMethod?: string;\n};\n\nconst ReceiptModal: FC<OwnProps & StateProps> = ({\n isOpen,\n onClose,\n prices,\n shippingPrices,\n totalAmount,\n currency,\n info,\n photoUrl,\n text,\n title,\n credentialsTitle,\n shippingMethod,\n}) => {\n const lang = useLang();\n const currencySign = getCurrencySign(currency);\n const checkoutInfo = useMemo(() => {\n return getCheckoutInfo(credentialsTitle, info, shippingMethod);\n }, [info, shippingMethod, credentialsTitle]);\n return (\n <Modal\n className=\"PaymentModal PaymentModal-receipt\"\n isOpen={isOpen}\n onClose={onClose}\n >\n <div>\n <div className=\"header\">\n <Button\n className=\"close-button\"\n color=\"translucent\"\n round\n size=\"smaller\"\n onClick={onClose}\n ariaLabel=\"Close\"\n >\n <i className=\"icon-close\" />\n </Button>\n <h3> {lang('PaymentReceipt')} </h3>\n </div>\n <div className=\"receipt-content custom-scroll\">\n <Checkout\n prices={prices}\n shippingPrices={shippingPrices}\n totalPrice={totalAmount}\n invoiceContent={{\n photoUrl,\n text,\n title,\n }}\n checkoutInfo={checkoutInfo}\n currency={currencySign}\n />\n </div>\n </div>\n </Modal>\n );\n};\n\nexport default memo(withGlobal<OwnProps>(\n (global): StateProps => {\n const { receipt } = global.payment;\n const {\n currency,\n prices: mapedPrices,\n info,\n totalAmount,\n credentialsTitle,\n shippingPrices,\n shippingMethod,\n photoUrl,\n text,\n title,\n } = (receipt || {});\n\n return {\n currency,\n prices: mapedPrices,\n info,\n totalAmount,\n credentialsTitle,\n shippingPrices,\n shippingMethod,\n photoUrl,\n text,\n title,\n };\n },\n)(ReceiptModal));\n\nfunction getCheckoutInfo(paymentMethod?: string,\n info?:\n { phone?: string;\n name?: string;\n shippingAddress?: ApiShippingAddress;\n },\n shippingMethod?: string) {\n if (!info) {\n return { paymentMethod };\n }\n const { shippingAddress } = info;\n const fullAddress = shippingAddress && shippingAddress.streetLine1\n ? `${shippingAddress.streetLine1}, ${shippingAddress.city}, ${shippingAddress.countryIso2}`\n : undefined;\n const { phone, name } = info;\n return {\n paymentMethod,\n paymentProvider: 'Stripe',\n shippingAddress: fullAddress,\n name,\n phone,\n shippingMethod,\n };\n}\n","import { ApiMediaFormat } from '../../../api/types';\n\nimport * as mediaLoader from '../../../util/mediaLoader';\n\n// @ts-ignore\nimport MonkeyIdle from '../../../assets/TwoFactorSetupMonkeyIdle.tgs';\n// @ts-ignore\nimport MonkeyTracking from '../../../assets/TwoFactorSetupMonkeyTracking.tgs';\n// @ts-ignore\nimport MonkeyClose from '../../../assets/TwoFactorSetupMonkeyClose.tgs';\n// @ts-ignore\nimport MonkeyPeek from '../../../assets/TwoFactorSetupMonkeyPeek.tgs';\n// @ts-ignore\nimport FoldersAll from '../../../assets/FoldersAll.tgs';\n// @ts-ignore\nimport FoldersNew from '../../../assets/FoldersNew.tgs';\n// @ts-ignore\nimport DiscussionGroups from '../../../assets/DiscussionGroupsDucks.tgs';\n\nexport const ANIMATED_STICKERS_PATHS = {\n MonkeyIdle,\n MonkeyTracking,\n MonkeyClose,\n MonkeyPeek,\n FoldersAll,\n FoldersNew,\n DiscussionGroups,\n};\n\nexport default function getAnimationData(name: keyof typeof ANIMATED_STICKERS_PATHS) {\n const path = ANIMATED_STICKERS_PATHS[name].replace(window.location.origin, '');\n\n return mediaLoader.fetch(`file${path}`, ApiMediaFormat.Lottie);\n}\n","export default __webpack_public_path__ + \"TwoFactorSetupMonkeyIdle.dea4a492c144df84ddab778dc8a3f0cd.tgs\";","export default __webpack_public_path__ + \"TwoFactorSetupMonkeyTracking.eb5a7a6f166fb7589c12e6248561fb58.tgs\";","export default __webpack_public_path__ + \"TwoFactorSetupMonkeyClose.604c4c833d322b7e6c3ea19bef058241.tgs\";","export default __webpack_public_path__ + \"TwoFactorSetupMonkeyPeek.1905436b042520363d7e59f5d7f903ab.tgs\";","export default __webpack_public_path__ + \"FoldersAll.3f9f9e243d19f0fbf9aaaff11cbd4572.tgs\";","export default __webpack_public_path__ + \"FoldersNew.9a40d71c0c8be70f5bd14ff2d7bc1593.tgs\";","export default __webpack_public_path__ + \"DiscussionGroupsDucks.9ea453d1be9d1b0ee77a992f8e587485.tgs\";","import React, {\n FC, useEffect, useState, memo,\n} from '../../lib/teact/teact';\n\nimport { DEBUG } from '../../config';\nimport { blobToFile, blobToDataUri } from '../../util/files';\nimport useLang from '../../hooks/useLang';\n\nimport Button from './Button';\nimport Modal from './Modal';\nimport Loading from './Loading';\n\nimport './CropModal.scss';\n\n// Change to 'base64' to get base64-encoded string\nconst cropperResultOptions: Croppie.ResultOptions & { type: 'blob' } = {\n type: 'blob',\n quality: 0.8,\n format: 'jpeg',\n circle: false,\n};\n\ntype ICroppie = typeof import('croppie');\nlet Croppie: ICroppie;\nlet croppiePromise: Promise<{ default: ICroppie }>;\n\nasync function ensureCroppie() {\n if (!croppiePromise) {\n croppiePromise = import('../../lib/croppie') as unknown as Promise<{ default: ICroppie }>;\n Croppie = (await croppiePromise).default;\n }\n\n return croppiePromise;\n}\n\nlet cropper: Croppie;\n\nasync function initCropper(imgFile: File) {\n try {\n const cropContainer = document.getElementById('avatar-crop');\n if (!cropContainer) {\n return;\n }\n\n const { offsetWidth, offsetHeight } = cropContainer;\n\n cropper = new Croppie(cropContainer, {\n enableZoom: true,\n boundary: {\n width: offsetWidth,\n height: offsetHeight,\n },\n viewport: {\n width: offsetWidth - 16,\n height: offsetHeight - 16,\n type: 'circle',\n },\n });\n\n const dataUri = await blobToDataUri(imgFile);\n await cropper.bind({ url: dataUri });\n } catch (err) {\n if (DEBUG) {\n // eslint-disable-next-line no-console\n console.error(err);\n }\n }\n}\n\ntype OwnProps = {\n file?: File;\n onChange: (file: File) => void;\n onClose: () => void;\n};\n\nconst CropModal: FC<OwnProps> = ({ file, onChange, onClose }: OwnProps) => {\n const [isCroppieReady, setIsCroppieReady] = useState(false);\n\n useEffect(() => {\n if (!file) {\n return;\n }\n\n if (!isCroppieReady) {\n ensureCroppie().then(() => setIsCroppieReady(true));\n\n return;\n }\n\n initCropper(file);\n }, [file, isCroppieReady]);\n\n const lang = useLang();\n\n async function handleCropClick() {\n if (!cropper) {\n return;\n }\n\n const result: Blob | string = await cropper.result(cropperResultOptions);\n const croppedImg = typeof result === 'string' ? result : blobToFile(result, 'avatar.jpg');\n\n onChange(croppedImg);\n }\n\n return (\n <Modal\n isOpen={Boolean(file)}\n onClose={onClose}\n title=\"Drag to reposition\"\n className=\"CropModal\"\n hasCloseButton\n >\n {isCroppieReady ? (\n <div id=\"avatar-crop\" />\n ) : (\n <Loading />\n )}\n <Button\n className=\"confirm-button\"\n round\n color=\"primary\"\n onClick={handleCropClick}\n ariaLabel={lang('CropImage')}\n >\n <i className=\"icon-check\" />\n </Button>\n </Modal>\n );\n};\n\nexport default memo(CropModal);\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, useState, useEffect, memo,\n} from '../../lib/teact/teact';\n\nimport buildClassName from '../../util/buildClassName';\n\nimport CropModal from './CropModal';\n\nimport './AvatarEditable.scss';\n\ninterface OwnProps {\n title?: string;\n disabled?: boolean;\n currentAvatarBlobUrl?: string;\n onChange: (file: File) => void;\n}\n\nconst AvatarEditable: FC<OwnProps> = ({\n title = 'Change your profile picture',\n disabled,\n currentAvatarBlobUrl,\n onChange,\n}) => {\n const [selectedFile, setSelectedFile] = useState<File | undefined>();\n const [croppedBlobUrl, setCroppedBlobUrl] = useState<string | undefined>(currentAvatarBlobUrl);\n\n useEffect(() => {\n setCroppedBlobUrl(currentAvatarBlobUrl);\n }, [currentAvatarBlobUrl]);\n\n function handleSelectFile(event: ChangeEvent<HTMLInputElement>) {\n const target = event.target as HTMLInputElement;\n\n if (!target || !target.files || !target.files[0]) {\n return;\n }\n\n setSelectedFile(target.files[0]);\n target.value = '';\n }\n\n function handleAvatarCrop(croppedImg: File) {\n setSelectedFile(undefined);\n onChange(croppedImg);\n\n if (croppedBlobUrl) {\n URL.revokeObjectURL(croppedBlobUrl);\n }\n setCroppedBlobUrl(URL.createObjectURL(croppedImg));\n }\n\n function handleModalClose() {\n setSelectedFile(undefined);\n }\n\n const labelClassName = buildClassName(\n croppedBlobUrl && 'filled',\n disabled && 'disabled',\n );\n\n return (\n <div className=\"AvatarEditable\">\n <label\n className={labelClassName}\n role=\"button\"\n tabIndex={0}\n title={title}\n >\n <input\n type=\"file\"\n onChange={handleSelectFile}\n accept=\"image/png, image/jpeg\"\n />\n <i className=\"icon-camera-add\" />\n {croppedBlobUrl && <img src={croppedBlobUrl} alt=\"Avatar\" />}\n </label>\n <CropModal file={selectedFile} onClose={handleModalClose} onChange={handleAvatarCrop} />\n </div>\n );\n};\n\nexport default memo(AvatarEditable);\n","import React, {\n FC, useState, useEffect, useCallback, memo,\n} from '../../lib/teact/teact';\n\nimport { STICKER_SIZE_AUTH, STICKER_SIZE_AUTH_MOBILE, STICKER_SIZE_TWO_FA } from '../../config';\nimport { IS_MOBILE_SCREEN } from '../../util/environment';\nimport getAnimationData from './helpers/animatedAssets';\n\nimport AnimatedSticker from './AnimatedSticker';\n\nimport './PasswordMonkey.scss';\n\ntype OwnProps = {\n isPasswordVisible: boolean;\n isBig?: boolean;\n};\n\nconst PEEK_MONKEY_SHOW_DELAY = 2000;\nconst SEGMENT_COVER_EYES: [number, number] = [0, 50];\nconst SEGMENT_UNCOVER_EYE: [number, number] = [0, 20];\nconst SEGMENT_COVER_EYE: [number, number] = [20, 0];\nconst STICKER_SIZE = IS_MOBILE_SCREEN ? STICKER_SIZE_AUTH_MOBILE : STICKER_SIZE_AUTH;\n\nconst PasswordMonkey: FC<OwnProps> = ({ isPasswordVisible, isBig }) => {\n const [closeMonkeyData, setCloseMonkeyData] = useState<Record<string, any>>();\n const [peekMonkeyData, setPeekMonkeyData] = useState<Record<string, any>>();\n const [isFirstMonkeyLoaded, setIsFirstMonkeyLoaded] = useState(false);\n const [isPeekShown, setIsPeekShown] = useState(false);\n\n useEffect(() => {\n if (!closeMonkeyData) {\n getAnimationData('MonkeyClose').then(setCloseMonkeyData);\n } else {\n setTimeout(() => setIsPeekShown(true), PEEK_MONKEY_SHOW_DELAY);\n }\n }, [closeMonkeyData]);\n\n useEffect(() => {\n if (!peekMonkeyData) {\n getAnimationData('MonkeyPeek').then(setPeekMonkeyData);\n }\n }, [peekMonkeyData]);\n\n const handleFirstMonkeyLoad = useCallback(() => setIsFirstMonkeyLoaded(true), []);\n\n return (\n <div id=\"monkey\" className={isBig ? 'big' : ''}>\n {!isFirstMonkeyLoaded && (\n <div className=\"monkey-preview\" />\n )}\n {closeMonkeyData && (\n <AnimatedSticker\n id=\"closeMonkey\"\n size={isBig ? STICKER_SIZE_TWO_FA : STICKER_SIZE}\n className={isPeekShown ? 'hidden' : 'shown'}\n animationData={closeMonkeyData}\n playSegment={SEGMENT_COVER_EYES}\n noLoop\n onLoad={handleFirstMonkeyLoad}\n />\n )}\n {peekMonkeyData && (\n <AnimatedSticker\n id=\"peekMonkey\"\n size={isBig ? STICKER_SIZE_TWO_FA : STICKER_SIZE}\n className={isPeekShown ? 'shown' : 'hidden'}\n animationData={peekMonkeyData}\n playSegment={isPasswordVisible ? SEGMENT_UNCOVER_EYE : SEGMENT_COVER_EYE}\n noLoop\n />\n )}\n </div>\n );\n};\n\nexport default memo(PasswordMonkey);\n","import { ChangeEvent } from 'react';\nimport React, {\n FC, memo, useEffect, useRef, useState,\n} from '../../lib/teact/teact';\n\nimport { MIN_PASSWORD_LENGTH } from '../../config';\nimport { IS_TOUCH_ENV, IS_MOBILE_SCREEN } from '../../util/environment';\nimport buildClassName from '../../util/buildClassName';\n\nimport Button from '../ui/Button';\n\ntype OwnProps = {\n submitLabel?: string;\n error?: string;\n hint?: string;\n placeholder?: string;\n isLoading?: boolean;\n isPasswordVisible?: boolean;\n clearError: NoneToVoidFunction;\n onChangePasswordVisibility: (state: boolean) => void;\n onInputChange?: (password: string) => void;\n onSubmit: (password: string) => void;\n};\n\nconst FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400;\n\nconst PasswordForm: FC<OwnProps> = ({\n isLoading = false,\n isPasswordVisible,\n error,\n hint,\n placeholder = 'Password',\n submitLabel = 'Next',\n clearError,\n onChangePasswordVisibility,\n onInputChange,\n onSubmit,\n}) => {\n // eslint-disable-next-line no-null/no-null\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [password, setPassword] = useState('');\n const [canSubmit, setCanSubmit] = useState(false);\n\n useEffect(() => {\n if (!IS_TOUCH_ENV) {\n setTimeout(() => {\n inputRef.current!.focus();\n }, FOCUS_DELAY_TIMEOUT_MS);\n }\n }, []);\n\n useEffect(() => {\n if (error) {\n requestAnimationFrame(() => {\n inputRef.current!.focus();\n inputRef.current!.select();\n });\n }\n }, [error]);\n\n function onPasswordChange(e: ChangeEvent<HTMLInputElement>) {\n if (error) {\n clearError();\n }\n\n const { target } = e;\n setPassword(target.value);\n setCanSubmit(target.value.length >= MIN_PASSWORD_LENGTH);\n if (onInputChange) {\n onInputChange(target.value);\n }\n }\n\n function togglePasswordVisibility() {\n onChangePasswordVisibility(!isPasswordVisible);\n }\n\n function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n\n if (isLoading) {\n return;\n }\n\n if (canSubmit) {\n onSubmit(password);\n }\n }\n\n return (\n <form action=\"\" onSubmit={handleSubmit} autoComplete=\"off\">\n <div className={buildClassName('input-group password-input', password && 'touched', error && 'error')}>\n <input\n ref={inputRef}\n className=\"form-control\"\n type={isPasswordVisible ? 'text' : 'password'}\n id=\"sign-in-password\"\n value={password || ''}\n autoComplete=\"current-password\"\n onChange={onPasswordChange}\n />\n <label>{error || hint || placeholder}</label>\n <div\n className=\"toggle-password\"\n onClick={togglePasswordVisibility}\n role=\"button\"\n tabIndex={0}\n title=\"Toggle password visibility\"\n >\n <i className={isPasswordVisible ? 'icon-eye' : 'icon-eye-closed'} />\n </div>\n </div>\n {canSubmit && (\n <Button type=\"submit\" ripple isLoading={isLoading}>\n {submitLabel}\n </Button>\n )}\n </form>\n );\n};\n\nexport default memo(PasswordForm);\n"],"sourceRoot":""} |