[Refactoring] Use optional chaining operator (#1400)

This commit is contained in:
Alexander Zinchuk 2021-08-27 21:05:46 +03:00
parent 30bf41a337
commit 98b3939dea
122 changed files with 240 additions and 262 deletions

View File

@ -22,7 +22,7 @@ export function buildApiThumbnailFromStripped(
}
const realSizes = sizes.filter((s): s is GramJs.PhotoSize => s instanceof GramJs.PhotoSize);
const { w, h } = realSizes && realSizes.length ? realSizes[realSizes.length - 1] : DEFAULT_THUMB_SIZE;
const { w, h } = realSizes.length ? realSizes[realSizes.length - 1] : DEFAULT_THUMB_SIZE;
const { bytes } = thumb;
const dataUri = bytesToDataUri(
!mimeType || mimeType === 'image/jpeg' ? strippedPhotoToJpg(bytes) : bytes,

View File

@ -171,7 +171,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM
...(keyboardButtons && { keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse }),
...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }),
...(mtpMessage.viaBotId && { viaBotId: mtpMessage.viaBotId }),
...(replies && replies.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }),
...(replies?.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }),
...(postAuthor && { adminTitle: postAuthor }),
};
}
@ -505,7 +505,7 @@ export function buildInvoice(media: GramJs.MessageMediaInvoice): ApiInvoice {
return {
text,
title,
photoUrl: photo && photo.url,
photoUrl: photo?.url,
receiptMsgId,
amount: Number(totalAmount),
currency,

View File

@ -34,7 +34,7 @@ export function buildStickerFromDocument(document: GramJs.TypeDocument): ApiStic
const stickerSetInfo = stickerAttribute && stickerAttribute.stickerset instanceof GramJs.InputStickerSetID
? stickerAttribute.stickerset
: undefined;
const emoji = stickerAttribute ? stickerAttribute.alt : undefined;
const emoji = stickerAttribute?.alt;
const isAnimated = document.mimeType === ANIMATED_STICKER_MIME_TYPE;
const cachedThumb = document.thumbs && document.thumbs.find(
(s): s is GramJs.PhotoCachedSize => s instanceof GramJs.PhotoCachedSize,
@ -83,7 +83,7 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
id: String(id),
accessHash: String(accessHash),
title,
hasThumbnail: Boolean(thumbs && thumbs.length),
hasThumbnail: Boolean(thumbs?.length),
count,
hash,
shortName,

View File

@ -23,7 +23,7 @@ export async function fetchStickerSets({ hash }: { hash: number }) {
}
allStickers.sets.forEach((stickerSet) => {
if (stickerSet.thumbs && stickerSet.thumbs.length) {
if (stickerSet.thumbs?.length) {
localDb.stickerSets[String(stickerSet.id)] = stickerSet;
}
});

View File

@ -57,7 +57,7 @@ export async function fetchFullUser({
export async function fetchNearestCountry() {
const dcInfo = await invokeRequest(new GramJs.help.GetNearestDc());
return dcInfo ? dcInfo.country : undefined;
return dcInfo?.country;
}
export async function fetchTopUsers({ hash = 0 }: { hash?: number }) {

View File

@ -117,7 +117,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
// eslint-disable-next-line no-underscore-dangle
const entities = update._entities;
if (entities && entities.length) {
if (entities?.length) {
entities
.filter((e) => e instanceof GramJs.User)
.map(buildApiUser)
@ -660,7 +660,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
});
} else if (update instanceof GramJs.UpdateUserName) {
const updatedUser = localDb.users[update.userId];
const user = updatedUser && updatedUser.mutualContact && !updatedUser.self
const user = updatedUser?.mutualContact && !updatedUser.self
? pick(update, ['username'])
: pick(update, ['firstName', 'lastName', 'username']);
@ -697,7 +697,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
return;
}
if (_entities && _entities.length) {
if (_entities?.length) {
_entities
.filter((e) => e instanceof GramJs.User && !e.contact)
.forEach((user) => {

View File

@ -88,10 +88,7 @@ function subscribeToWorker(onUpdate: OnApiUpdate) {
}
}
} else if (data.type === 'methodCallback') {
const requestState = requestStates.get(data.messageId);
if (requestState && requestState.callback) {
requestState.callback(...data.callbackArgs);
}
requestStates.get(data.messageId)?.callback?.(...data.callbackArgs);
} else if (data.type === 'unhandledError') {
throw data.error;
}

View File

@ -89,7 +89,7 @@ const CountryCodeInput: FC<OwnProps> = ({
const inputValue = filter !== undefined
? filter
: (value && value.name) || '';
: (value?.name) || '';
return (
<div className={buildClassName('input-group', value && 'touched')}>

View File

@ -44,7 +44,7 @@ const AnimatedEmoji: FC<OwnProps> = ({
const isIntersecting = useIsIntersecting(ref, observeIntersection);
const thumbDataUri = sticker.thumbnail && sticker.thumbnail.dataUri;
const thumbDataUri = sticker.thumbnail?.dataUri;
const previewBlobUrl = useMedia(
`${localMediaHash}?size=m`,
!isIntersecting && !forceLoadPreview,

View File

@ -77,7 +77,7 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
const formattedNumber = phoneNumber && formatPhoneNumberWithCode(phoneNumber);
const link = getChatLink(chat);
const description = (fullInfo && fullInfo.bio) || getChatDescription(chat);
const description = (fullInfo?.bio) || getChatDescription(chat);
return (
<div className="ChatExtra">

View File

@ -57,7 +57,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
deleteScheduledMessages,
}) => {
const handleDeleteMessageForAll = useCallback(() => {
const messageIds = album && album.messages
const messageIds = album?.messages
? album.messages.map(({ id }) => id)
: [message.id];
deleteMessages({ messageIds, shouldDeleteForAll: true });
@ -65,7 +65,7 @@ const DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
}, [deleteMessages, message.id, onClose, album]);
const handleDeleteMessageForSelf = useCallback(() => {
const messageIds = album && album.messages
const messageIds = album?.messages
? album.messages.map(({ id }) => id)
: [message.id];
if (isSchedule) {

View File

@ -38,7 +38,7 @@ const GifButton: FC<OwnProps> = ({
const isIntersecting = useIsIntersecting(ref, observeIntersection);
const loadAndPlay = isIntersecting && !isDisabled;
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !loadAndPlay, ApiMediaFormat.BlobUrl);
const thumbRef = useCanvasBlur(gif.thumbnail && gif.thumbnail.dataUri, Boolean(previewBlobUrl));
const thumbRef = useCanvasBlur(gif.thumbnail?.dataUri, Boolean(previewBlobUrl));
const videoData = useMedia(localMediaHash, !loadAndPlay, ApiMediaFormat.BlobUrl);
const shouldRenderVideo = Boolean(loadAndPlay && videoData);
const { transitionClassNames } = useTransitionForMedia(hasThumbnail || previewBlobUrl || videoData, 'slow');

View File

@ -104,7 +104,7 @@ const Picker: FC<OwnProps> = ({
/>
</div>
{viewportIds && viewportIds.length ? (
{viewportIds?.length ? (
<InfiniteScroll
className="picker-list custom-scroll"
items={viewportIds}

View File

@ -59,7 +59,7 @@ const PickerSelectedItem: FC<OwnProps & StateProps> = ({
chat={chat}
user={user}
size="small"
isSavedMessages={user && user.isSelf}
isSavedMessages={user?.isSelf}
/>
);

View File

@ -130,7 +130,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
) : (
<div className="title">
<h3 dir="auto">{fullName && renderText(fullName)}</h3>
{user && user.isVerified && <VerifiedIcon />}
{user?.isVerified && <VerifiedIcon />}
</div>
)}
{(status || (!isSavedMessages && !noStatusOrTyping)) && renderStatusOrTyping()}

View File

@ -54,7 +54,7 @@ const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
const { id: userId } = user || {};
const { id: chatId } = chat || {};
const fullName = user ? getUserFullName(user) : (chat ? chat.title : '');
const photos = (user ? user.photos : (chat ? chat.photos : undefined)) || [];
const photos = user?.photos || chat?.photos || [];
const slideAnimation = animationLevel >= 1 ? 'slide' : 'none';
const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0);
@ -171,14 +171,14 @@ const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
return (
<span className="status" dir="auto">{
isChatChannel(chat!)
? lang('Subscribers', chat!.membersCount, 'i')
: lang('Members', chat!.membersCount, 'i')
? lang('Subscribers', chat!.membersCount ?? 0, 'i')
: lang('Members', chat!.membersCount ?? 0, 'i')
}
</span>
);
}
const isVerifiedIconShown = (user && user.isVerified) || (chat && chat.isVerified);
const isVerifiedIconShown = (user || chat)?.isVerified;
return (
<div className={buildClassName('ProfileInfo', forceShowSelf && 'self')} dir={lang.isRtl ? 'rtl' : undefined}>

View File

@ -87,7 +87,7 @@ const StickerButton: FC<OwnProps> = ({
<div
ref={ref}
className={fullClassName}
title={title || (sticker && sticker.emoji)}
title={title || (sticker?.emoji)}
// @ts-ignore
style={style}
data-sticker-id={sticker.id}

View File

@ -94,7 +94,7 @@ const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({
hasCloseButton
title={stickerSet ? renderText(stickerSet.title, ['emoji', 'links']) : lang('AccDescrStickerSet')}
>
{stickerSet && stickerSet.stickers ? (
{stickerSet?.stickers ? (
<>
<div ref={containerRef} className="stickers custom-scroll">
{stickerSet.stickers.map((sticker) => (

View File

@ -126,7 +126,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
const actionTargetUsers = useMemo(() => {
return actionTargetUserIds
? actionTargetUserIds.map((userId) => usersById && usersById[userId]).filter<ApiUser>(Boolean as any)
? actionTargetUserIds.map((userId) => usersById?.[userId]).filter<ApiUser>(Boolean as any)
: undefined;
}, [actionTargetUserIds, usersById]);
@ -205,7 +205,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
return <TypingStatus typingStatus={typingStatus} />;
}
if (draft && draft.text.length) {
if (draft?.text.length) {
return (
<p className="last-message" dir={lang.isRtl ? 'auto' : 'ltr'}>
<span className="draft">{lang('Draft')}</span>
@ -273,7 +273,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
chat={chat}
user={privateChatUser}
withOnlineStatus
isSavedMessages={privateChatUser && privateChatUser.isSelf}
isSavedMessages={privateChatUser?.isSelf}
lastSyncTime={lastSyncTime}
/>
</div>

View File

@ -111,7 +111,7 @@ const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({
{ title: lang.code === 'en' ? 'All' : lang('FilterAllChats') },
...displayedFolders.map((folder) => ({
title: folder.title,
...(folderCountersById && folderCountersById[folder.id]),
...(folderCountersById?.[folder.id]),
})),
];
}, [displayedFolders, folderCountersById, lang]);
@ -220,7 +220,7 @@ const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({
return (
<div className="ChatFolders">
{folderTabs && folderTabs.length ? (
{folderTabs?.length ? (
<TabList tabs={folderTabs} activeTab={activeChatFolder} onSwitchTab={handleSwitchTab} />
) : shouldRenderPlaceholder ? (
<div className={buildClassName('tabs-placeholder', transitionClassNames)} />

View File

@ -206,7 +206,7 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
noFastList
noScrollRestore
>
{viewportIds && viewportIds.length && chatArrays ? (
{viewportIds?.length && chatArrays ? (
renderChats()
) : viewportIds && !viewportIds.length ? (
(

View File

@ -77,7 +77,7 @@ const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({
return (
<InfiniteScroll items={viewportIds} onLoadMore={getMore} className="chat-list custom-scroll">
{viewportIds && viewportIds.length ? (
{viewportIds?.length ? (
viewportIds.map((id) => (
<ListItem
key={id}

View File

@ -179,7 +179,7 @@ export default memo(withGlobal<OwnProps>(
chatsById,
localContactIds,
searchQuery,
isSearching: fetchingStatus && fetchingStatus.chats,
isSearching: fetchingStatus?.chats,
globalUserIds,
localUserIds,
};

View File

@ -67,7 +67,7 @@ const AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];
return globalMessagesByChatId[chatId]?.byId[messageId];
}).filter(Boolean);
}, [globalMessagesByChatId, foundIds]);

View File

@ -84,7 +84,7 @@ const ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({
chat={chat}
user={privateChatUser}
withOnlineStatus
isSavedMessages={privateChatUser && privateChatUser.isSelf}
isSavedMessages={privateChatUser?.isSelf}
lastSyncTime={lastSyncTime}
/>
<div className="info">

View File

@ -72,9 +72,7 @@ const ChatMessageResults: FC<OwnProps & StateProps & DispatchProps> = ({
.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
return (
globalMessagesByChatId && globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId]
);
return globalMessagesByChatId?.[chatId]?.byId[messageId];
})
.filter<ApiMessage>(Boolean as any)
.sort((a, b) => b.date - a.date);
@ -133,7 +131,7 @@ export default memo(withGlobal<OwnProps>(
const { currentUserId, messages: { byChatId: globalMessagesByChatId }, lastSyncTime } = global;
const { fetchingStatus, resultsByType } = global.globalSearch;
const { foundIds } = (resultsByType && resultsByType.text) || {};
const { foundIds } = (resultsByType?.text) || {};
return {
currentUserId,

View File

@ -144,9 +144,7 @@ const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
return (
globalMessagesByChatId && globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId]
);
return globalMessagesByChatId?.[chatId]?.byId[messageId];
})
.filter<ApiMessage>(Boolean as any)
.sort((a, b) => b.date - a.date);
@ -300,7 +298,7 @@ export default memo(withGlobal<OwnProps>(
const { chatIds: globalChatIds, userIds: globalUserIds } = globalResults || {};
const { chatIds: localChatIds, userIds: localUserIds } = localResults || {};
const { byChatId: globalMessagesByChatId } = messages;
const { foundIds } = (resultsByType && resultsByType.text) || {};
const foundIds = resultsByType?.text?.foundIds;
return {
currentUserId,

View File

@ -64,7 +64,7 @@ const FileResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
const message = globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];
const message = globalMessagesByChatId[chatId]?.byId[messageId];
return message && getMessageDocument(message) ? message : undefined;
}).filter(Boolean) as ApiMessage[];

View File

@ -63,7 +63,7 @@ const LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];
return globalMessagesByChatId[chatId]?.byId[messageId];
}).filter(Boolean);
}, [globalMessagesByChatId, foundIds]);

View File

@ -62,7 +62,7 @@ const MediaResults: FC<OwnProps & StateProps & DispatchProps> = ({
return foundIds.map((id) => {
const [chatId, messageId] = id.split('_').map(Number);
return globalMessagesByChatId[chatId] && globalMessagesByChatId[chatId].byId[messageId];
return globalMessagesByChatId[chatId]?.byId[messageId];
}).filter(Boolean);
}, [globalMessagesByChatId, foundIds]);

View File

@ -28,10 +28,10 @@ export function createMapStateToProps(type: ApiGlobalMessageSearchType) {
// One component is used for two different types of results.
// The differences between them are only in the isVoice property.
// The rest of the search results use their own personal components.
const currentType = type !== 'audio' ? type : (props && props.isVoice ? 'voice' : 'audio');
const currentType = type !== 'audio' ? type : (props?.isVoice ? 'voice' : 'audio');
const { byChatId: globalMessagesByChatId } = global.messages;
const { foundIds } = (resultsByType && resultsByType[currentType]) || {};
const foundIds = resultsByType?.[currentType]?.foundIds;
return {
theme: selectTheme(global),

View File

@ -97,7 +97,7 @@ const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({
}, [loadStickerSets]);
useEffect(() => {
if (stickerSetIds && stickerSetIds.length) {
if (stickerSetIds?.length) {
loadAddedStickers();
}
}, [stickerSetIds, loadAddedStickers]);
@ -127,7 +127,7 @@ const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({
}, [openModal]);
const stickerSets = stickerSetIds && stickerSetIds.map((id: string) => {
return stickerSetsById && stickerSetsById[id] && stickerSetsById[id].installedDate ? stickerSetsById[id] : false;
return stickerSetsById?.[id]?.installedDate ? stickerSetsById[id] : false;
}).filter<ApiStickerSet>(Boolean as any);
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.General);

View File

@ -95,7 +95,7 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
const handleWallPaperSelect = useCallback((slug: string) => {
setThemeSettings({ theme: themeRef.current, background: slug });
const currentWallpaper = loadedWallpapers && loadedWallpapers.find((wallpaper) => wallpaper.slug === slug);
if (currentWallpaper && currentWallpaper.document.thumbnail) {
if (currentWallpaper?.document.thumbnail) {
getAverageColor(currentWallpaper.document.thumbnail.dataUri)
.then((color) => {
const patternColor = getPatternColor(color);
@ -113,7 +113,7 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.GeneralChatBackground);
const isUploading = loadedWallpapers && loadedWallpapers[0] && loadedWallpapers[0].slug === UPLOADING_WALLPAPER_SLUG;
const isUploading = loadedWallpapers?.[0] && loadedWallpapers[0].slug === UPLOADING_WALLPAPER_SLUG;
return (
<div className="SettingsGeneralBackground settings-content custom-scroll">

View File

@ -109,6 +109,8 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));
markIsDragging();
return true;
}
captureEvents(colorPickerRef.current!, {
@ -126,6 +128,8 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
setHsb(positions2hsb({ colorPosition, huePosition }, rectsRef.current!));
markIsDragging();
return true;
}
captureEvents(huePickerRef.current!, {

View File

@ -36,7 +36,7 @@ const SettingsMain: FC<OwnProps & StateProps & DispatchProps> = ({
lastSyncTime,
}) => {
const lang = useLang();
const profileId = currentUser ? currentUser.id : undefined;
const profileId = currentUser?.id;
useEffect(() => {
if (profileId && lastSyncTime) {

View File

@ -227,11 +227,11 @@ export default memo(withGlobal<OwnProps>(
sessionsCount: activeSessions.length,
isSensitiveEnabled,
canChangeSensitive,
visibilityPrivacyPhoneNumber: privacy.phoneNumber && privacy.phoneNumber.visibility,
visibilityPrivacyLastSeen: privacy.lastSeen && privacy.lastSeen.visibility,
visibilityPrivacyProfilePhoto: privacy.profilePhoto && privacy.profilePhoto.visibility,
visibilityPrivacyForwarding: privacy.forwards && privacy.forwards.visibility,
visibilityPrivacyGroupChats: privacy.chatInvite && privacy.chatInvite.visibility,
visibilityPrivacyPhoneNumber: privacy.phoneNumber?.visibility,
visibilityPrivacyLastSeen: privacy.lastSeen?.visibility,
visibilityPrivacyProfilePhoto: privacy.profilePhoto?.visibility,
visibilityPrivacyForwarding: privacy.forwards?.visibility,
visibilityPrivacyGroupChats: privacy.chatInvite?.visibility,
};
},
(setGlobal, actions): DispatchProps => pick(actions, [

View File

@ -82,7 +82,7 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps & DispatchProps> = (
<Avatar size="medium" user={user} chat={chat} />
<div className="contact-info" dir="auto">
<h3 dir="auto">{renderText((isPrivate ? getUserFullName(user) : getChatTitle(lang, chat!)) || '')}</h3>
{user && user.phoneNumber && (
{user?.phoneNumber && (
<div className="contact-phone" dir="auto">{formatPhoneNumberWithCode(user.phoneNumber)}</div>
)}
{user && !user.phoneNumber && user.username && (
@ -103,7 +103,7 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps & DispatchProps> = (
</div>
<div className="chat-list custom-scroll">
{blockedIds && blockedIds.length ? (
{blockedIds?.length ? (
<div className="scroll-container">
{blockedIds!.map((contactId, i) => renderContact(contactId, i, 0))}
</div>

View File

@ -32,7 +32,7 @@ const SettingsStickerSet: FC<OwnProps> = ({
return undefined;
}
const firstSticker = stickerSet.stickers && stickerSet.stickers[0];
const firstSticker = stickerSet.stickers?.[0];
if (stickerSet.hasThumbnail || !firstSticker) {
return (

View File

@ -37,7 +37,7 @@ const WallpaperTile: FC<OwnProps> = ({
const localBlobUrl = document.previewBlobUrl;
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
const thumbRef = useCanvasBlur(
document.thumbnail && document.thumbnail.dataUri,
document.thumbnail?.dataUri,
Boolean(previewBlobUrl),
true,
);

View File

@ -203,7 +203,7 @@ const SettingsFoldersChatsPicker: FC<OwnProps> = ({
</>
)}
{viewportIds && viewportIds.length ? (
{viewportIds?.length ? (
viewportIds.map(renderItem)
) : viewportIds && !viewportIds.length ? (
<p className="no-results" key="no-results">Sorry, nothing found.</p>

View File

@ -98,8 +98,8 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps & DispatchProps> = ({
const [visibleIncludedChatIds, visibleExcludedChatIds] = useMemo(() => {
const allLoadedChatsSet = new Set([
...loadedActiveChatIds || [],
...loadedArchivedChatIds || [],
...(loadedActiveChatIds || []),
...(loadedArchivedChatIds || []),
]);
const loadedIncludedChatIds = findIntersectionWithSet(includedChatIds, allLoadedChatsSet);

View File

@ -172,7 +172,7 @@ const SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({
<div className="settings-item pt-3">
<h4 className="settings-item-header mb-3" dir={lang.isRtl ? 'rtl' : undefined}>{lang('Filters')}</h4>
{userFolders && userFolders.length ? userFolders.map((folder) => (
{userFolders?.length ? userFolders.map((folder) => (
<ListItem
className="mb-2 no-icon"
narrow

View File

@ -87,8 +87,8 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
const chatIds = useMemo(() => {
const listIds = [
...activeListIds || [],
...archivedListIds || [],
...(activeListIds || []),
...(archivedListIds || []),
];
let priorityIds = pinnedIds || [];
@ -158,7 +158,7 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
className="ForwardPicker"
header={modalHeader}
>
{viewportIds && viewportIds.length ? (
{viewportIds?.length ? (
<InfiniteScroll
className="picker-list custom-scroll"
items={viewportIds}

View File

@ -343,7 +343,7 @@ function getNodes(origin: MediaViewerOrigin, message?: ApiMessage) {
return {
container,
mediaEl: mediaEls && mediaEls[mediaEls.length - 1],
mediaEl: mediaEls?.[mediaEls.length - 1],
};
}

View File

@ -85,7 +85,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
const targetUsers = useMemo(() => {
return targetUserIds
? targetUserIds.map((userId) => usersById && usersById[userId]).filter<ApiUser>(Boolean as any)
? targetUserIds.map((userId) => usersById?.[userId]).filter<ApiUser>(Boolean as any)
: undefined;
}, [targetUserIds, usersById]);

View File

@ -94,7 +94,7 @@ const ContactGreeting: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>(
(global, { userId }): StateProps => {
const { stickers } = global.stickers.greeting;
const sticker = stickers && stickers.length ? stickers[userId % stickers.length] : undefined;
const sticker = stickers?.length ? stickers[userId % stickers.length] : undefined;
const chat = selectChat(global, userId);
if (!chat) {
return {};

View File

@ -208,7 +208,7 @@ export default memo(withGlobal<OwnProps>(
const chat = selectChat(global, chatId);
const isChannel = Boolean(chat && isChatChannel(chat));
if (chat && chat.isRestricted) {
if (chat?.isRestricted) {
return {
noMenu: true,
};

View File

@ -445,7 +445,7 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
&& (!listItemElementsRef.current || listItemElementsRef.current.length === 0)
)
|| checkSingleMessageActionByType('contactSignUp', messageGroups)
|| (lastMessage && lastMessage.content.action && lastMessage.content.action.type === 'contactSignUp')
|| (lastMessage?.content.action && lastMessage.content.action.type === 'contactSignUp')
);
const isGroupChatJustCreated = isGroupChat && isCreator
&& checkSingleMessageActionByType('chatCreate', messageGroups);

View File

@ -436,11 +436,11 @@ export default memo(withGlobal(
canPost: !isPinnedMessageList && (!chat || canPost) && !isBotNotStarted,
isPinnedMessageList,
isScheduledMessageList,
currentUserBannedRights: chat && chat.currentUserBannedRights,
defaultBannedRights: chat && chat.defaultBannedRights,
currentUserBannedRights: chat?.currentUserBannedRights,
defaultBannedRights: chat?.defaultBannedRights,
hasPinnedOrAudioMessage: (
threadId !== MAIN_THREAD_ID
|| Boolean(pinnedIds && pinnedIds.length)
|| Boolean(pinnedIds?.length)
|| Boolean(audioChatId && audioMessageId)
),
pinnedMessagesCount: pinnedIds ? pinnedIds.length : 0,

View File

@ -430,10 +430,10 @@ export default memo(withGlobal<OwnProps>(
let messagesCount: number | undefined;
if (messageListType === 'pinned') {
const pinnedIds = selectPinnedIds(global, chatId);
messagesCount = pinnedIds && pinnedIds.length;
messagesCount = pinnedIds?.length;
} else if (messageListType === 'scheduled') {
const scheduledIds = selectScheduledIds(global, chatId);
messagesCount = scheduledIds && scheduledIds.length;
messagesCount = scheduledIds?.length;
} else if (messageListType === 'thread' && threadId !== MAIN_THREAD_ID) {
const threadInfo = selectThreadInfo(global, chatId, threadId);
if (threadInfo) {
@ -479,7 +479,7 @@ export default memo(withGlobal<OwnProps>(
}
const pinnedMessageIds = selectPinnedIds(global, chatId);
if (pinnedMessageIds && pinnedMessageIds.length) {
if (pinnedMessageIds?.length) {
const firstPinnedMessage = messagesById[pinnedMessageIds[0]];
const {
canUnpin,

View File

@ -158,7 +158,7 @@ const MobileSearchFooter: FC<StateProps & DispatchProps> = ({
<div className="footer">
<div className="counter">
{query ? (
foundIds && foundIds.length ? (
foundIds?.length ? (
`${focusedIndex + 1} of ${totalCount}`
) : foundIds && !foundIds.length ? (
'No results'

View File

@ -40,7 +40,7 @@ const PinnedMessageNavigation: FC<OwnProps> = ({
} = markupParams;
const firstChild = containerRef.current.firstElementChild;
if (containerRef && containerRef.current) {
if (containerRef?.current) {
const currentElement = containerRef.current;
const { style } = currentElement;
style.height = `${trackHeight}px`;

View File

@ -125,7 +125,7 @@ const AttachmentModal: FC<OwnProps> = ({
const { dataTransfer: { files } } = e;
if (files && files.length) {
if (files?.length) {
const newFiles = isQuick
? Array.from(files).filter((file) => {
return file.type && CONTENT_TYPES_FOR_QUICK_UPLOAD.has(file.type);

View File

@ -1097,16 +1097,16 @@ export default memo(withGlobal<OwnProps>(
withScheduledButton: (
threadId === MAIN_THREAD_ID
&& messageListType === 'thread'
&& Boolean(scheduledIds && scheduledIds.length)
&& Boolean(scheduledIds?.length)
),
shouldSchedule: messageListType === 'scheduled',
botKeyboardMessageId,
botKeyboardPlaceholder: keyboardMessage ? keyboardMessage.keyboardPlaceholder : undefined,
botKeyboardPlaceholder: keyboardMessage?.keyboardPlaceholder,
isForwarding: chatId === global.forwardMessages.toChatId,
isPollModalOpen: global.isPollModalOpen,
stickersForEmoji: global.stickers.forEmoji.stickers,
groupChatMembers: chat && chat.fullInfo && chat.fullInfo.members,
topInlineBotIds: global.topInlineBots && global.topInlineBots.userIds,
groupChatMembers: chat?.fullInfo?.members,
topInlineBotIds: global.topInlineBots?.userIds,
currentUserId: global.currentUserId,
usersById: global.users.byId,
lastSyncTime: global.lastSyncTime,
@ -1115,8 +1115,8 @@ export default memo(withGlobal<OwnProps>(
isReceiptModalOpen: Boolean(global.payment.receipt),
shouldSuggestStickers: global.settings.byKey.shouldSuggestStickers,
recentEmojis: global.recentEmojis,
baseEmojiKeywords: baseEmojiKeywords ? baseEmojiKeywords.keywords : undefined,
emojiKeywords: emojiKeywords ? emojiKeywords.keywords : undefined,
baseEmojiKeywords: baseEmojiKeywords?.keywords,
emojiKeywords: emojiKeywords?.keywords,
serverTimeOffset: global.serverTimeOffset,
inlineBots: global.inlineBots.byUsername,
isInlineBotLoading: global.inlineBots.isLoading,

View File

@ -124,7 +124,7 @@ const EmojiPicker: FC<OwnProps & StateProps> = ({
return MEMO_EMPTY_ARRAY;
}
const themeCategories = [...categories];
if (recentEmojis && recentEmojis.length) {
if (recentEmojis?.length) {
themeCategories.unshift({
id: 'recent',
name: lang('RecentStickers'),

View File

@ -92,7 +92,7 @@ const InlineBotTooltip: FC<OwnProps & DispatchProps> = ({
}, [botId, openChat, startBot, switchPm]);
const prevInlineBotResults = usePrevious(
inlineBotResults && inlineBotResults.length
inlineBotResults?.length
? inlineBotResults
: undefined,
shouldRender,

View File

@ -35,7 +35,7 @@ const MentionTooltip: FC<OwnProps> = ({
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
const handleUserSelect = useCallback((userId: number, forceFocus = false) => {
const user = usersById && usersById[userId];
const user = usersById?.[userId];
if (!user) {
return;
}
@ -66,7 +66,7 @@ const MentionTooltip: FC<OwnProps> = ({
}, [filteredUsers, onClose]);
const prevChatMembers = usePrevious(
filteredUsers && filteredUsers.length
filteredUsers?.length
? filteredUsers
: undefined,
shouldRender,
@ -86,7 +86,7 @@ const MentionTooltip: FC<OwnProps> = ({
return (
<div className={className} ref={containerRef}>
{renderedChatMembers && renderedChatMembers.map(({ id }, index) => (
{renderedChatMembers?.map(({ id }, index) => (
<ListItem
key={id}
className="chat-item-clickable scroll-item"

View File

@ -131,7 +131,7 @@ const StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({
const noPopulatedSets = useMemo(() => (
areAddedLoaded
&& allSets.filter((set) => set.stickers && set.stickers.length).length === 0
&& allSets.filter((set) => set.stickers?.length).length === 0
), [allSets, areAddedLoaded]);
useEffect(() => {
@ -143,7 +143,7 @@ const StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({
}, [loadAndPlay, loadFavoriteStickers, loadRecentStickers, loadStickerSets]);
useEffect(() => {
if (addedSetIds && addedSetIds.length) {
if (addedSetIds?.length) {
loadAddedStickers();
}
}, [addedSetIds, loadAddedStickers]);
@ -184,7 +184,7 @@ const StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({
const canRenderContents = useAsyncRendering([], SLIDE_TRANSITION_DURATION);
function renderCover(stickerSet: StickerSetOrRecent, index: number) {
const firstSticker = stickerSet.stickers && stickerSet.stickers[0];
const firstSticker = stickerSet.stickers?.[0];
const buttonClassName = buildClassName(
'symbol-set-button sticker-set-button',
index === activeSetIndex && 'activated',

View File

@ -62,7 +62,7 @@ const StickerTooltip: FC<OwnProps & StateProps & DispatchProps> = ({
const className = buildClassName(
'StickerTooltip composer-tooltip custom-scroll',
transitionClassNames,
!(displayedStickers && displayedStickers.length) && 'hidden',
!(displayedStickers?.length) && 'hidden',
);
return (

View File

@ -43,7 +43,7 @@ export default (
}
if (pastedText) {
insertTextAndUpdateCursor(pastedText, input ? input.id : undefined);
insertTextAndUpdateCursor(pastedText, input?.id);
}
}

View File

@ -21,7 +21,7 @@ export default function useInlineBotTooltip(
const usernameLowered = username.toLowerCase();
const prevQuery = usePrevious(query);
const prevUsername = usePrevious(username);
const inlineBotData = inlineBots && inlineBots[usernameLowered];
const inlineBotData = inlineBots?.[usernameLowered];
const {
id: botId,
switchPm,
@ -50,7 +50,7 @@ export default function useInlineBotTooltip(
}, [offset, chatId, query, queryInlineBot, usernameLowered]);
useEffect(() => {
if (isAllowed && botId && (switchPm || (results && results.length))) {
if (isAllowed && botId && (switchPm || (results?.length))) {
markIsOpen();
} else {
unmarkIsOpen();

View File

@ -38,7 +38,7 @@ export default function useMentionTooltip(
const [usersToMention, setUsersToMention] = useState<ApiUser[] | undefined>();
const topInlineBots = useMemo(() => {
return (topInlineBotIds || []).map((id) => usersById && usersById[id]).filter<ApiUser>(Boolean as any);
return (topInlineBotIds || []).map((id) => usersById?.[id]).filter<ApiUser>(Boolean as any);
}, [topInlineBotIds, usersById]);
const getFilteredUsers = useCallback((filter, withInlineBots: boolean) => {
@ -83,7 +83,7 @@ export default function useMentionTooltip(
}, [canSuggestMembers, html, getFilteredUsers, markIsOpen, unmarkIsOpen]);
useEffect(() => {
if (usersToMention && usersToMention.length) {
if (usersToMention?.length) {
markIsOpen();
} else {
unmarkIsOpen();

View File

@ -50,7 +50,7 @@ const MediaResult: FC<OwnProps> = ({
return (
<div className="MediaResult chat-item-clickable" onClick={handleClick}>
{shouldRenderThumb && (
<img src={(photo && photo.thumbnail && photo.thumbnail.dataUri) || thumbnailDataUrl} alt="" />
<img src={(photo?.thumbnail?.dataUri) || thumbnailDataUrl} alt="" />
)}
{shouldRenderFullMedia && (
<img src={mediaBlobUrl} className={`${transitionClassNames} full-media`} alt="" />
@ -64,7 +64,7 @@ const MediaResult: FC<OwnProps> = ({
return (
<BaseResult
focus={focus}
thumbUrl={shouldRenderFullMedia ? mediaBlobUrl : (thumbnail && thumbnail.dataUri) || thumbnailDataUrl}
thumbUrl={shouldRenderFullMedia ? mediaBlobUrl : (thumbnail?.dataUri) || thumbnailDataUrl}
transitionClassNames={shouldRenderFullMedia ? transitionClassNames : undefined}
title={title}
description={description}

View File

@ -1,10 +1,10 @@
export function formatCardExpiry(input: string) {
input = input.replace(/[^\d]/g, '').slice(0, 4);
const parts = input.match(/.{1,2}/g);
if (parts && parts[0] && Number(parts[0]) > 12) {
if (parts?.[0] && Number(parts[0]) > 12) {
parts[0] = '12';
}
if (parts && parts[0] && parts[0].length === 2 && !parts[1]) {
if (parts?.[0] && parts[0].length === 2 && !parts[1]) {
parts[1] = '';
}
return parts ? parts.join('/') : '';

View File

@ -59,13 +59,13 @@ const Album: FC<OwnProps & StateProps & DispatchProps> = ({
function renderAlbumMessage(message: ApiMessage, index: number) {
const { photo, video } = getMessageContent(message);
const fileUpload = uploadsById[message.previousLocalId || message.id];
const uploadProgress = fileUpload ? fileUpload.progress : undefined;
const uploadProgress = fileUpload?.progress;
const { dimensions, sides } = albumLayout.layout[index];
if (photo) {
const shouldAffectAppendix = hasCustomAppendix && (
// eslint-disable-next-line no-bitwise
isOwn ? index === mediaCount - 1 : Boolean(sides & AlbumRectPart.Left && sides & AlbumRectPart.Bottom)
(isOwn ? index === mediaCount - 1 : Boolean(sides & AlbumRectPart.Left && sides & AlbumRectPart.Bottom))
);
return (

View File

@ -152,7 +152,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({
const handleForward = useCallback(() => {
closeMenu();
if (album && album.messages) {
if (album?.messages) {
const messageIds = album.messages.map(({ id }) => id);
openForwardMenu({ fromChatId: message.chatId, messageIds });
} else {
@ -171,7 +171,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({
}, [closeMenu, message.content.sticker, unfaveSticker]);
const handleSelectMessage = useCallback(() => {
const params = album && album.messages
const params = album?.messages
? {
messageId: message.id,
childMessageIds: album.messages.map(({ id }) => id),

View File

@ -290,7 +290,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
toggleMessageSelection({
messageId,
groupedId,
...(e && e.shiftKey && { withShift: true }),
...(e?.shiftKey && { withShift: true }),
...(isAlbum && { childMessageIds: album!.messages.map(({ id }) => id) }),
});
}, [isLocal, toggleMessageSelection, messageId, isAlbum, album]);
@ -432,9 +432,9 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
function renderAvatar() {
const isAvatarPeerUser = avatarPeer && isChatPrivate(avatarPeer.id);
const avatarUser = avatarPeer && isAvatarPeerUser ? avatarPeer as ApiUser : undefined;
const avatarChat = avatarPeer && !isAvatarPeerUser ? avatarPeer as ApiChat : undefined;
const hiddenName = !avatarPeer && forwardInfo ? forwardInfo.hiddenUserName : undefined;
const avatarUser = (avatarPeer && isAvatarPeerUser) ? avatarPeer as ApiUser : undefined;
const avatarChat = (avatarPeer && !isAvatarPeerUser) ? avatarPeer as ApiChat : undefined;
const hiddenName = (!avatarPeer && forwardInfo) ? forwardInfo.hiddenUserName : undefined;
return (
<Avatar
@ -616,7 +616,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
if (!asForwarded) {
senderColor = `color-${getUserColorKey(senderPeer)}`;
}
} else if (forwardInfo && forwardInfo.hiddenUserName) {
} else if (forwardInfo?.hiddenUserName) {
senderTitle = forwardInfo.hiddenUserName;
}
@ -644,7 +644,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
</span>
</>
)}
{forwardInfo && forwardInfo.isLinkedChannelPost ? (
{forwardInfo?.isLinkedChannelPost ? (
<span className="admin-title" dir="auto">{lang('DiscussChannel')}</span>
) : message.adminTitle && !isChannel ? (
<span className="admin-title" dir="auto">{message.adminTitle}</span>
@ -795,7 +795,7 @@ export default memo(withGlobal<OwnProps>(
const chat = selectChat(global, chatId);
const isChatWithSelf = selectIsChatWithSelf(global, chatId);
const isChannel = chat && isChatChannel(chat);
const chatUsername = chat && chat.username;
const chatUsername = chat?.username;
const forceSenderName = !isChatWithSelf && isAnonymousOwnMessage(message);
const canShowSender = withSenderName || withAvatar || forceSenderName;
@ -830,7 +830,7 @@ export default memo(withGlobal<OwnProps>(
const singleEmoji = getMessageSingleEmoji(message);
let isSelected: boolean;
if (album && album.messages) {
if (album?.messages) {
isSelected = album.messages.every(({ id: messageId }) => selectIsMessageSelected(global, messageId));
} else {
isSelected = selectIsMessageSelected(global, id);

View File

@ -28,7 +28,7 @@ const PollOption: FC<OwnProps> = ({
}) => {
const result = voteResults && voteResults.find((r) => r.option === answer.option);
const correctAnswer = correctResults.length === 0 || correctResults.indexOf(answer.option) !== -1;
const showIcon = (correctResults.length > 0 && correctAnswer) || (result && result.isChosen);
const showIcon = (correctResults.length > 0 && correctAnswer) || (result?.isChosen);
const answerPercent = result ? getPercentage(result.votersCount, totalVoters || 0) : 0;
const [finalPercent, setFinalPercent] = useState(shouldAnimate ? 0 : answerPercent);
// eslint-disable-next-line no-null/no-null

View File

@ -107,7 +107,7 @@ const Video: FC<OwnProps> = ({
setPlayProgress(Math.max(0, e.currentTarget.currentTime - 1));
}, []);
const duration = (videoRef.current && videoRef.current.duration) || video.duration || 0;
const duration = (videoRef.current?.duration) || video.duration || 0;
const isOwn = isOwnMessage(message);
const isForwarded = isForwardedMessage(message);

View File

@ -43,7 +43,7 @@ const WebPage: FC<OwnProps> = ({
const webPage = getMessageWebPage(message);
let isSquarePhoto = false;
if (webPage && webPage.photo && !webPage.video) {
if (webPage?.photo && !webPage.video) {
const { width, height } = calculateMediaDimensions(message);
isSquarePhoto = width === height;
}

View File

@ -49,7 +49,7 @@ export function buildContentClassName(
if (customShape) {
classNames.push('custom-shape');
if (video && video.isRound) {
if (video?.isRound) {
classNames.push('round');
}

View File

@ -44,9 +44,7 @@ export function getMessageCopyOptions(
if (text) {
// Detect if the user has selection in the current message
const hasSelection = Boolean((
selection
&& selection.anchorNode
&& selection.anchorNode.parentNode
selection?.anchorNode?.parentNode
&& (selection.anchorNode.parentNode as HTMLElement).closest('.Message .content-inner')
&& selection.toString().replace(/(?:\r\n|\r|\n)/g, '') !== ''
));

View File

@ -40,7 +40,7 @@ export default function withSelectControl(WrappedComponent: FC) {
const handleMessageSelect = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
toggleMessageSelection({ messageId: message.id, withShift: e && e.shiftKey });
toggleMessageSelection({ messageId: message.id, withShift: e?.shiftKey });
}, [toggleMessageSelection, message]);
const newProps = useMemo(() => {

View File

@ -93,7 +93,7 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps & DispatchProps> = ({
}, [step, error]);
useEffect(() => {
if (error && error.field) {
if (error?.field) {
paymentDispatch({
type: 'setFormErrors',
payload: {
@ -416,7 +416,7 @@ function findShippingOption(shippingOptions: ShippingOption[], optionId: string)
function getShippingPrices(shippingOptions: ShippingOption[], shippingOption: string) {
const option = findShippingOption(shippingOptions, shippingOption);
return option ? option.prices : undefined;
return option?.prices;
}
function getTotalPrice(prices: Price[] = [], shippingOptions: ShippingOption[] | undefined, shippingOption: string) {
@ -439,7 +439,7 @@ function getCheckoutInfo(state: FormState, shippingOptions: ShippingOption[] | u
: undefined;
const { phone, fullName: name } = state;
const shippingOption = shippingOptions ? findShippingOption(shippingOptions, state.shipping) : undefined;
const shippingMethod = shippingOption ? shippingOption.title : undefined;
const shippingMethod = shippingOption?.title;
return {
paymentMethod,
paymentProvider,

View File

@ -136,7 +136,7 @@ function getCheckoutInfo(paymentMethod?: string,
return { paymentMethod };
}
const { shippingAddress } = info;
const fullAddress = shippingAddress && shippingAddress.streetLine1
const fullAddress = shippingAddress?.streetLine1
? `${shippingAddress.streetLine1}, ${shippingAddress.city}, ${shippingAddress.countryIso2}`
: undefined;
const { phone, name } = info;

View File

@ -186,7 +186,7 @@ export default memo(withGlobal<OwnProps>(
return {
isChannel,
members: chat && chat.fullInfo ? chat.fullInfo.members : undefined,
members: chat?.fullInfo?.members,
currentUserId,
usersById,
chatsById,

View File

@ -136,8 +136,8 @@ export default memo(withGlobal<OwnProps>(
const { voters, offsets } = global.pollResults;
return {
voters: voters && voters[answer.option],
offset: (offsets && offsets[answer.option]) || '',
voters: voters?.[answer.option],
offset: (offsets?.[answer.option]) || '',
};
},
(global, actions): DispatchProps => pick(actions, ['loadPollOptionResults', 'openChat', 'closePollResults']),

View File

@ -438,7 +438,7 @@ export default memo(withGlobal<OwnProps>(
const isGroup = chat && isChatGroup(chat);
const isChannel = chat && isChatChannel(chat);
const hasMembersTab = isGroup || (isChannel && isChatAdmin(chat!));
const members = chat && chat.fullInfo && chat.fullInfo.members;
const members = chat?.fullInfo?.members;
const areMembersHidden = hasMembersTab && chat && chat.fullInfo && !chat.fullInfo.canViewMembers;
const canAddMembers = hasMembersTab && chat && (getHasAdminRight(chat, 'inviteUsers') || chat.isCreator);
const canDeleteMembers = hasMembersTab && chat && (getHasAdminRight(chat, 'banUsers') || chat.isCreator);
@ -463,7 +463,7 @@ export default memo(withGlobal<OwnProps>(
canDeleteMembers,
currentUserId: global.currentUserId,
isRightColumnShown: selectIsRightColumnShown(global),
isRestricted: chat && chat.isRestricted,
isRestricted: chat?.isRestricted,
lastSyncTime: global.lastSyncTime,
serverTimeOffset: global.serverTimeOffset,
...(hasMembersTab && members && {

View File

@ -135,7 +135,7 @@ const RightSearch: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
const handleKeyDown = useKeyboardListNavigation(containerRef, true, (index) => {
const foundResult = foundResults && foundResults[index === -1 ? 0 : index];
const foundResult = foundResults?.[index === -1 ? 0 : index];
if (foundResult) {
foundResult.onClick();
}

View File

@ -41,7 +41,7 @@ const StickerSetResult: FC<OwnProps & StateProps & DispatchProps> = ({
}) => {
const lang = useLang();
const isAdded = set && Boolean(set.installedDate);
const areStickersLoaded = Boolean(set && set.stickers);
const areStickersLoaded = Boolean(set?.stickers);
const [isModalOpen, openModal, closeModal] = useFlag();
@ -57,7 +57,7 @@ const StickerSetResult: FC<OwnProps & StateProps & DispatchProps> = ({
const coverStickerIds = (set.covers || []).map(({ id }) => id);
const otherStickers = set.stickers ? set.stickers.filter(({ id }) => !coverStickerIds.includes(id)) : [];
return [...set.covers || [], ...otherStickers].slice(0, STICKERS_TO_DISPLAY);
return [...(set.covers || []), ...otherStickers].slice(0, STICKERS_TO_DISPLAY);
}, [set]);
useEffect(() => {

View File

@ -63,8 +63,8 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
isActive,
}) => {
const currentTitle = chat ? (chat.title || '') : '';
const currentAbout = chat && chat.fullInfo ? (chat.fullInfo.about || '') : '';
const hasLinkedChat = chat && chat.fullInfo && chat.fullInfo.linkedChatId;
const currentAbout = chat?.fullInfo ? (chat.fullInfo.about || '') : '';
const hasLinkedChat = chat?.fullInfo?.linkedChatId;
const [isDeleteDialogOpen, openDeleteDialog, closeDeleteDialog] = useFlag();
const [isProfileFieldsTouched, setIsProfileFieldsTouched] = useState(false);
@ -85,7 +85,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
}
}, [progress]);
const adminsCount = (chat && chat.fullInfo && chat.fullInfo.adminMembers && chat.fullInfo.adminMembers.length) || 0;
const adminsCount = (chat?.fullInfo?.adminMembers?.length) || 0;
const handleClickEditType = useCallback(() => {
onScreenSelect(ManagementScreens.ChatPrivacyType);
@ -220,7 +220,7 @@ const ManageChannel: FC<OwnProps & StateProps & DispatchProps> = ({
onClick={handleClickSubscribers}
>
<span className="title" dir="auto">{lang('ChannelSubscribers')}</span>
<span className="subtitle" dir="auto">{lang('Subscribers', chat.membersCount!, 'i')}</span>
<span className="subtitle" dir="auto">{lang('Subscribers', chat.membersCount ?? 0, 'i')}</span>
</ListItem>
</div>
<div className="section">
@ -257,7 +257,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId)!;
const { progress } = global.management;
const isSignaturesShown = Boolean(chat && chat.isSignaturesShown);
const isSignaturesShown = Boolean(chat?.isSignaturesShown);
return {
chat,

View File

@ -54,7 +54,7 @@ const ManageChatPrivacyType: FC<OwnProps & StateProps & DispatchProps> = ({
updatePrivateLink,
}) => {
const isPublic = Boolean(chat.username);
const privateLink = chat.fullInfo && chat.fullInfo.inviteLink;
const privateLink = chat.fullInfo?.inviteLink;
const [privacyType, setPrivacyType] = useState<PrivacyType>(isPublic ? 'public' : 'private');
const [username, setUsername] = useState();

View File

@ -62,7 +62,7 @@ const ManageDiscussion: FC<OwnProps & StateProps & DispatchProps> = ({
const [isConfirmUnlinkGroupDialogOpen, openConfirmUnlinkGroupDialog, closeConfirmUnlinkGroupDialog] = useFlag();
const [isConfirmLinkGroupDialogOpen, openConfirmLinkGroupDialog, closeConfirmLinkGroupDialog] = useFlag();
const lang = useLang();
const linkedChatId = linkedChat && linkedChat.id;
const linkedChatId = linkedChat?.id;
useHistoryBack(isActive, onClose);
@ -261,7 +261,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId);
const { forDiscussionIds, byId: chatsByIds } = global.chats;
const linkedChat = chat && chat.fullInfo && chat.fullInfo.linkedChatId
const linkedChat = chat?.fullInfo?.linkedChatId
? selectChat(global, chat.fullInfo.linkedChatId)
: undefined;

View File

@ -185,7 +185,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
return totalCount;
}, [chat]);
const adminsCount = (chat.fullInfo && chat.fullInfo.adminMembers && chat.fullInfo.adminMembers.length) || 0;
const adminsCount = (chat.fullInfo?.adminMembers?.length) || 0;
const handleDeleteGroup = useCallback(() => {
if (isBasicGroup) {
@ -273,7 +273,7 @@ const ManageGroup: FC<OwnProps & StateProps & DispatchProps> = ({
<div className="section">
<ListItem icon="group" multiline onClick={handleClickMembers}>
<span className="title">{lang('GroupMembers')}</span>
<span className="subtitle">{formatInteger(chat.membersCount!)}</span>
<span className="subtitle">{formatInteger(chat.membersCount ?? 0)}</span>
</ListItem>
{chat.fullInfo && (
@ -326,7 +326,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId)!;
const { progress } = global.management;
const hasLinkedChannel = Boolean(chat.fullInfo && chat.fullInfo.linkedChatId);
const hasLinkedChannel = Boolean(chat.fullInfo?.linkedChatId);
const isBasicGroup = isChatBasicGroup(chat);
return {

View File

@ -73,14 +73,14 @@ const ManageGroupAdminRights: FC<OwnProps & StateProps & DispatchProps> = ({
}, [chat, selectedChatMemberId]);
useEffect(() => {
if (chat && chat.fullInfo && selectedChatMemberId && !selectedChatMember) {
if (chat?.fullInfo && selectedChatMemberId && !selectedChatMember) {
onScreenSelect(ManagementScreens.ChatAdministrators);
}
}, [chat, onScreenSelect, selectedChatMember, selectedChatMemberId]);
useEffect(() => {
setPermissions((selectedChatMember && selectedChatMember.adminRights) || {});
setCustomTitle(((selectedChatMember && selectedChatMember.customTitle) || '').substr(0, CUSTOM_TITLE_MAX_LENGTH));
setPermissions((selectedChatMember?.adminRights) || {});
setCustomTitle(((selectedChatMember?.customTitle) || '').substr(0, CUSTOM_TITLE_MAX_LENGTH));
setIsTouched(false);
setIsLoading(false);
}, [selectedChatMember]);

View File

@ -84,7 +84,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId);
const { byId: usersById } = global.users;
const members = chat && chat.fullInfo && chat.fullInfo.members;
const members = chat?.fullInfo?.members;
const isChannel = chat && isChatChannel(chat);
return {

View File

@ -88,7 +88,7 @@ const ManageGroupPermissions: FC<OwnProps & StateProps & DispatchProps> = ({
}, [currentUserId, onChatMemberSelect, onScreenSelect]);
useEffect(() => {
setPermissions((chat && chat.defaultBannedRights) || {});
setPermissions((chat?.defaultBannedRights) || {});
setHavePermissionChanged(false);
setTimeout(() => {
setIsLoading(false);
@ -148,7 +148,7 @@ const ManageGroupPermissions: FC<OwnProps & StateProps & DispatchProps> = ({
return Object.keys(bannedRights).reduce((result, key) => {
if (
!bannedRights[key as keyof ApiChatBannedRights]
|| (defaultBannedRights && defaultBannedRights[key as keyof ApiChatBannedRights])
|| (defaultBannedRights?.[key as keyof ApiChatBannedRights])
|| key === 'sendInline' || key === 'viewMessages' || key === 'sendGames'
) {
return result;

View File

@ -62,13 +62,13 @@ const ManageGroupUserPermissions: FC<OwnProps & StateProps & DispatchProps> = ({
}, [chat, selectedChatMemberId]);
useEffect(() => {
if (chat && chat.fullInfo && selectedChatMemberId && !selectedChatMember) {
if (chat?.fullInfo && selectedChatMemberId && !selectedChatMember) {
onScreenSelect(ManagementScreens.GroupPermissions);
}
}, [chat, onScreenSelect, selectedChatMember, selectedChatMemberId]);
useEffect(() => {
setPermissions((selectedChatMember && selectedChatMember.bannedRights) || (chat && chat.defaultBannedRights) || {});
setPermissions((selectedChatMember?.bannedRights) || (chat?.defaultBannedRights) || {});
setHavePermissionChanged(false);
setIsLoading(false);
}, [chat, selectedChatMember]);

View File

@ -89,7 +89,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId);
const { byId: usersById } = global.users;
const members = chat && chat.fullInfo && chat.fullInfo.members;
const members = chat?.fullInfo?.members;
const isChannel = chat && isChatChannel(chat);
return {

View File

@ -154,7 +154,7 @@ const InfiniteScroll: FC<OwnProps> = ({
const nextAnchor = listItemElements[0];
if (nextAnchor) {
const nextAnchorTop = nextAnchor.getBoundingClientRect().top;
const newAnchorTop = currentAnchor && currentAnchor.offsetParent && currentAnchor !== nextAnchor
const newAnchorTop = currentAnchor?.offsetParent && currentAnchor !== nextAnchor
? currentAnchor.getBoundingClientRect().top
: nextAnchorTop;
const isMovingUp = (
@ -175,7 +175,7 @@ const InfiniteScroll: FC<OwnProps> = ({
const nextAnchor = listItemElements[listLength - 1];
if (nextAnchor) {
const nextAnchorTop = nextAnchor.getBoundingClientRect().top;
const newAnchorTop = currentAnchor && currentAnchor.offsetParent && currentAnchor !== nextAnchor
const newAnchorTop = currentAnchor?.offsetParent && currentAnchor !== nextAnchor
? currentAnchor.getBoundingClientRect().top
: nextAnchorTop;
const isMovingDown = (
@ -193,7 +193,7 @@ const InfiniteScroll: FC<OwnProps> = ({
}
if (!isUpdated) {
if (currentAnchor && currentAnchor.offsetParent) {
if (currentAnchor?.offsetParent) {
stateRef.current.currentAnchorTop = currentAnchor.getBoundingClientRect().top;
} else {
const nextAnchor = listItemElements[0];

View File

@ -182,7 +182,7 @@ const Transition: FC<OwnProps> = ({
}
const watchedNode = name === 'mv-slide'
? childNodes[activeIndex] && childNodes[activeIndex].firstChild
? childNodes[activeIndex]?.firstChild
: name === 'reveal' && isBackwards
? childNodes[prevActiveIndex]
: childNodes[activeIndex];

View File

@ -81,7 +81,7 @@ function getSuggestedFolderName(includeFilters?: FolderIncludeFilters) {
if (
Object.values(filters).filter(Boolean).length > 1
|| (includedChatIds && includedChatIds.length)
|| (includedChatIds?.length)
) {
return '';
}

View File

@ -44,9 +44,7 @@ export default (
}
}
if (handlers && handlers[eventName]) {
handlers[eventName](e);
}
handlers?.[eventName]?.(e);
}, onForcePlay);
const { proxy } = controllerRef.current!;

View File

@ -37,7 +37,7 @@ export default ({
return undefined;
}
const isChatWithSelf = privateChatUser && privateChatUser.isSelf;
const isChatWithSelf = privateChatUser?.isSelf;
const actionUnreadMark = chat.unreadCount || chat.hasUnreadMark
? { title: lang('MarkAsRead'), icon: 'readchats', handler: () => toggleChatUnread({ id: chat.id }) }

View File

@ -9,10 +9,10 @@ import { getMessageMediaThumbDataUri } from '../modules/helpers';
export default function useWebpThumbnail(message?: ApiMessage) {
const thumbnail = message && getMessageMediaThumbDataUri(message);
const { sticker } = (message && message.content) || {};
const sticker = message?.content?.sticker;
const shouldDecodeThumbnail = thumbnail && sticker && !isWebpSupported() && thumbnail.includes('image/webp');
const [thumbnailDecoded, setThumbnailDecoded] = useState(EMPTY_IMAGE_DATA_URI);
const messageId = message && message.id;
const messageId = message?.id;
useLayoutEffect(() => {
if (!shouldDecodeThumbnail) {

View File

@ -221,7 +221,7 @@ async function signInUserWithQrCode(
await Promise.race([updatePromise, inputPromise]);
} catch (err) {
if (err.message === 'RESTART_AUTH') {
return signInUser(client, apiCredentials, authParams);
return await signInUser(client, apiCredentials, authParams);
}
throw err;

View File

@ -90,7 +90,7 @@ addReducer('openChat', (global, actions, payload) => {
const { currentUserId } = global;
const chat = selectChat(global, id);
if (chat && chat.hasUnreadMark) {
if (chat?.hasUnreadMark) {
actions.toggleChatUnread({ id });
}
@ -162,7 +162,7 @@ addReducer('loadMoreChats', (global, actions, payload) => {
const oldestChat = listIds
? listIds
.map((id) => global.chats.byId[id])
.filter((chat) => Boolean(chat && chat.lastMessage) && !selectIsChatPinned(global, chat.id))
.filter((chat) => Boolean(chat?.lastMessage) && !selectIsChatPinned(global, chat.id))
.sort((chat1, chat2) => (chat1.lastMessage!.date - chat2.lastMessage!.date))[0]
: undefined;
@ -402,7 +402,7 @@ addReducer('editChatFolder', (global, actions, payload) => {
addReducer('addChatFolder', (global, actions, payload) => {
const { folder } = payload!;
const { orderedIds } = global.chatFolders;
const maxId = orderedIds && orderedIds.length ? Math.max.apply(Math.max, orderedIds) : ARCHIVED_FOLDER_ID;
const maxId = orderedIds?.length ? Math.max.apply(Math.max, orderedIds) : ARCHIVED_FOLDER_ID;
void createChatFolder(folder, maxId);
});
@ -738,7 +738,7 @@ addReducer('unlinkDiscussionGroup', (global, actions, payload) => {
}
let chat: ApiChat | undefined;
if (channel.fullInfo && channel.fullInfo.linkedChatId) {
if (channel.fullInfo?.linkedChatId) {
chat = selectChat(global, channel.fullInfo.linkedChatId);
}
@ -768,7 +768,7 @@ addReducer('loadMoreMembers', (global) => {
return;
}
const offset = (chat.fullInfo && chat.fullInfo.members && chat.fullInfo.members.length) || undefined;
const offset = (chat.fullInfo?.members?.length) || undefined;
const result = await callApi('fetchMembers', chat.id, chat.accessHash!, 'recent', offset);
if (!result) {
return;

View File

@ -57,7 +57,7 @@ addReducer('searchMessagesGlobal', (global, actions, payload) => {
} = global.globalSearch;
const maxDate = date ? timestampPlusDay(date) : date;
const { type } = payload;
const { nextOffsetId } = (resultsByType && resultsByType[type as ApiGlobalMessageSearchType]) || {};
const nextOffsetId = (resultsByType?.[type as ApiGlobalMessageSearchType])?.nextOffsetId;
const chat = chatId ? selectChat(global, chatId) : undefined;

View File

@ -29,12 +29,12 @@ addReducer('searchTextMessagesLocal', (global) => {
}
const { query, results } = currentSearch;
const offsetId = results ? results.nextOffsetId : undefined;
const offsetId = results?.nextOffsetId;
let topMessageId: number | undefined;
if (threadId !== MAIN_THREAD_ID) {
const threadInfo = selectThreadInfo(global, chatId!, threadId);
topMessageId = threadInfo ? threadInfo.topMessageId : undefined;
topMessageId = threadInfo?.topMessageId;
}
void searchTextMessages(chat, threadId, topMessageId, query, offsetId);
@ -53,7 +53,7 @@ addReducer('searchMediaMessagesLocal', (global) => {
const { currentType: type, resultsByType } = currentSearch;
const currentResults = type && resultsByType && resultsByType[type];
const offsetId = currentResults ? currentResults.nextOffsetId : undefined;
const offsetId = currentResults?.nextOffsetId;
if (!type) {
return;

View File

@ -420,7 +420,7 @@ addReducer('deleteHistory', (global, actions, payload) => {
return;
}
const maxId = chat.lastMessage && chat.lastMessage.id;
const maxId = chat.lastMessage?.id;
await callApi('deleteHistory', { chat, shouldDeleteForAll, maxId });

Some files were not shown because too many files have changed in this diff Show More