import type { FC } from '../../../lib/teact/teact'; import { memo, useCallback, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiPrivacySettings } from '../../../api/types'; import type { GlobalState } from '../../../global/types'; import type { CustomPeerType, UniqueCustomPeer } from '../../../types'; import { SettingsScreens } from '../../../types'; import { ALL_FOLDER_ID, ARCHIVED_FOLDER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config'; import { isChatChannel, isDeletedUser, } from '../../../global/helpers'; import { filterPeersByQuery } from '../../../global/helpers/peers'; import { unique } from '../../../util/iteratees'; import { CUSTOM_PEER_PREMIUM } from '../../../util/objects/customPeer'; import { getPrivacyKey } from './helpers/privacy'; import { useFolderManagerForOrderedIds } from '../../../hooks/useFolderManager'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; import useOldLang from '../../../hooks/useOldLang'; import Icon from '../../common/icons/Icon'; import PeerPicker from '../../common/pickers/PeerPicker'; import FloatingActionButton from '../../ui/FloatingActionButton'; export type OwnProps = { isAllowList?: boolean; withPremiumCategory?: boolean; withMiniAppsCategory?: boolean; usersOnly?: boolean; screen: SettingsScreens; isActive?: boolean; onReset: () => void; }; type StateProps = { currentUserId?: string; settings?: ApiPrivacySettings; }; const PREMIUM_CATEGORY = [CUSTOM_PEER_PREMIUM]; const SettingsPrivacyVisibilityExceptionList: FC = ({ isAllowList, withPremiumCategory, withMiniAppsCategory, screen, isActive, currentUserId, settings, usersOnly = false, onReset, }) => { const { setPrivacySettings } = getActions(); const oldLang = useOldLang(); const lang = useLang(); const customPeerBots: UniqueCustomPeer = useMemo(() => { return { isCustomPeer: true, type: 'bots', title: lang('PrivacyValueBots'), avatarIcon: 'bots', isAvatarSquare: true, peerColorId: 6, }; }, [lang]); const miniAppsCategory = useMemo(() => { return [customPeerBots]; }, [customPeerBots]); const selectedContactIds = useMemo(() => { if (!settings) { return []; } if (isAllowList) { return [...settings.allowUserIds, ...settings.allowChatIds]; } else { return [...settings.blockUserIds, ...settings.blockChatIds]; } }, [isAllowList, settings]); const selectedCategoryTypes = useMemo(() => { if (!settings) { return []; } if (settings.shouldAllowPremium) { return [CUSTOM_PEER_PREMIUM.type]; } if (settings.botsPrivacy === 'allow' && isAllowList) { return [customPeerBots.type]; } return []; }, [settings, isAllowList, customPeerBots]); const [searchQuery, setSearchQuery] = useState(''); const [isSubmitShown, setIsSubmitShown] = useState(false); const [newSelectedContactIds, setNewSelectedContactIds] = useState(selectedContactIds); const [newSelectedCategoryTypes, setNewSelectedCategoryTypes] = useState(selectedCategoryTypes); // Reset selected contact ids on change from other client when screen is not active useEffect(() => { if (!isActive) { setNewSelectedContactIds(selectedContactIds); setNewSelectedCategoryTypes(selectedCategoryTypes); } }, [isActive, selectedCategoryTypes, selectedContactIds]); const folderAllOrderedIds = useFolderManagerForOrderedIds(ALL_FOLDER_ID); const folderArchivedOrderedIds = useFolderManagerForOrderedIds(ARCHIVED_FOLDER_ID); const displayedIds = useMemo(() => { // No need for expensive global updates on chats, so we avoid them const chatsById = getGlobal().chats.byId; const usersById = getGlobal().users.byId; const chatIds = unique([...folderAllOrderedIds || [], ...folderArchivedOrderedIds || []]) .filter((chatId) => { const chat = chatsById[chatId]; const user = usersById[chatId]; const isDeleted = user && isDeletedUser(user); const isChannel = chat && isChatChannel(chat); return (!usersOnly || user) && chatId !== currentUserId && chatId !== SERVICE_NOTIFICATIONS_USER_ID && !isChannel && !isDeleted; }); const filteredChats = filterPeersByQuery({ ids: chatIds, query: searchQuery }); // Show only relevant items if (searchQuery) return filteredChats; return unique([ ...selectedContactIds, ...chatIds, ]); }, [folderAllOrderedIds, folderArchivedOrderedIds, selectedContactIds, searchQuery, currentUserId, usersOnly]); const handleSelectedCategoriesChange = useCallback((value: CustomPeerType[]) => { setNewSelectedCategoryTypes(value); setIsSubmitShown(true); }, []); const handleSelectedContactIdsChange = useCallback((value: string[]) => { setNewSelectedContactIds(value); setIsSubmitShown(true); }, []); const handleSubmit = useCallback(() => { setPrivacySettings({ privacyKey: getPrivacyKey(screen)!, isAllowList: Boolean(isAllowList), updatedIds: newSelectedContactIds, isPremiumAllowed: newSelectedCategoryTypes.includes(CUSTOM_PEER_PREMIUM.type) || undefined, botsPrivacy: (!withMiniAppsCategory) ? 'none' : (newSelectedCategoryTypes.includes(customPeerBots.type) ? 'allow' : 'disallow'), }); onReset(); }, [ isAllowList, withMiniAppsCategory, newSelectedCategoryTypes, newSelectedContactIds, onReset, screen, customPeerBots, ]); useHistoryBack({ isActive, onBack: onReset, }); function getCustomCategory() { if (withPremiumCategory) return PREMIUM_CATEGORY; if (withMiniAppsCategory && isAllowList) return miniAppsCategory; return undefined; } return (
); }; function getCurrentPrivacySettings(global: GlobalState, screen: SettingsScreens) { const { privacy } = global.settings; switch (screen) { case SettingsScreens.PrivacyPhoneNumberAllowedContacts: case SettingsScreens.PrivacyPhoneNumberDeniedContacts: return privacy.phoneNumber; case SettingsScreens.PrivacyLastSeenAllowedContacts: case SettingsScreens.PrivacyLastSeenDeniedContacts: return privacy.lastSeen; case SettingsScreens.PrivacyProfilePhotoAllowedContacts: case SettingsScreens.PrivacyProfilePhotoDeniedContacts: return privacy.profilePhoto; case SettingsScreens.PrivacyBioAllowedContacts: case SettingsScreens.PrivacyBioDeniedContacts: return privacy.bio; case SettingsScreens.PrivacyBirthdayAllowedContacts: case SettingsScreens.PrivacyBirthdayDeniedContacts: return privacy.birthday; case SettingsScreens.PrivacyGiftsAllowedContacts: case SettingsScreens.PrivacyGiftsDeniedContacts: return privacy.gifts; case SettingsScreens.PrivacyPhoneCallAllowedContacts: case SettingsScreens.PrivacyPhoneCallDeniedContacts: return privacy.phoneCall; case SettingsScreens.PrivacyPhoneP2PAllowedContacts: case SettingsScreens.PrivacyPhoneP2PDeniedContacts: return privacy.phoneP2P; case SettingsScreens.PrivacyForwardingAllowedContacts: case SettingsScreens.PrivacyForwardingDeniedContacts: return privacy.forwards; case SettingsScreens.PrivacyVoiceMessagesAllowedContacts: case SettingsScreens.PrivacyVoiceMessagesDeniedContacts: return privacy.voiceMessages; case SettingsScreens.PrivacyGroupChatsDeniedContacts: case SettingsScreens.PrivacyGroupChatsAllowedContacts: return privacy.chatInvite; case SettingsScreens.PrivacyNoPaidMessages: return privacy.noPaidMessages; } return undefined; } export default memo(withGlobal( (global, { screen }): StateProps => { return { currentUserId: global.currentUserId, settings: getCurrentPrivacySettings(global, screen), }; }, )(SettingsPrivacyVisibilityExceptionList));