432 lines
14 KiB
TypeScript
432 lines
14 KiB
TypeScript
import type { FC } from '../../../lib/teact/teact';
|
|
import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
|
|
import { getActions, withGlobal } from '../../../global';
|
|
|
|
import type { ApiPhoto, ApiPrivacySettings, BotsPrivacyType } from '../../../api/types';
|
|
import { SettingsScreens } from '../../../types';
|
|
|
|
import { selectIsCurrentUserPremium, selectUserFullInfo } from '../../../global/selectors';
|
|
import { getPrivacyKey } from './helpers/privacy';
|
|
|
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
|
import useLang from '../../../hooks/useLang';
|
|
import useLastCallback from '../../../hooks/useLastCallback';
|
|
import useOldLang from '../../../hooks/useOldLang';
|
|
|
|
import ListItem from '../../ui/ListItem';
|
|
import RadioGroup from '../../ui/RadioGroup';
|
|
import PremiumStatusItem from './PremiumStatusItem';
|
|
import PrivacyLockedOption from './PrivacyLockedOption';
|
|
import SettingsPrivacyLastSeen from './SettingsPrivacyLastSeen';
|
|
import SettingsPrivacyPublicProfilePhoto from './SettingsPrivacyPublicProfilePhoto';
|
|
|
|
type OwnProps = {
|
|
screen: SettingsScreens;
|
|
isActive?: boolean;
|
|
onScreenSelect: (screen: SettingsScreens) => void;
|
|
onReset: () => void;
|
|
};
|
|
|
|
type StateProps = {
|
|
currentUserId: string;
|
|
hasCurrentUserFullInfo?: boolean;
|
|
currentUserFallbackPhoto?: ApiPhoto;
|
|
primaryPrivacy?: ApiPrivacySettings;
|
|
secondaryPrivacy?: ApiPrivacySettings;
|
|
isPremiumRequired?: boolean;
|
|
};
|
|
|
|
const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
|
screen,
|
|
isActive,
|
|
primaryPrivacy,
|
|
secondaryPrivacy,
|
|
currentUserId,
|
|
hasCurrentUserFullInfo,
|
|
currentUserFallbackPhoto,
|
|
isPremiumRequired,
|
|
onScreenSelect,
|
|
onReset,
|
|
}) => {
|
|
useHistoryBack({
|
|
isActive,
|
|
onBack: onReset,
|
|
});
|
|
|
|
const secondaryScreen = useMemo(() => {
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyPhoneCall:
|
|
return SettingsScreens.PrivacyPhoneP2P;
|
|
case SettingsScreens.PrivacyPhoneNumber: {
|
|
return primaryPrivacy?.visibility === 'nobody' ? SettingsScreens.PrivacyAddByPhone : undefined;
|
|
}
|
|
default:
|
|
return undefined;
|
|
}
|
|
}, [primaryPrivacy, screen]);
|
|
|
|
return (
|
|
<div className="settings-content custom-scroll">
|
|
<PrivacySubsection
|
|
screen={screen}
|
|
privacy={primaryPrivacy}
|
|
onScreenSelect={onScreenSelect}
|
|
isPremiumRequired={isPremiumRequired}
|
|
/>
|
|
{screen === SettingsScreens.PrivacyProfilePhoto && primaryPrivacy?.visibility !== 'everybody' && (
|
|
<SettingsPrivacyPublicProfilePhoto
|
|
currentUserId={currentUserId}
|
|
hasCurrentUserFullInfo={hasCurrentUserFullInfo}
|
|
currentUserFallbackPhoto={currentUserFallbackPhoto}
|
|
/>
|
|
)}
|
|
{screen === SettingsScreens.PrivacyLastSeen && (
|
|
<SettingsPrivacyLastSeen visibility={primaryPrivacy?.visibility} />
|
|
)}
|
|
{secondaryScreen && (
|
|
<PrivacySubsection
|
|
screen={secondaryScreen}
|
|
privacy={secondaryPrivacy}
|
|
onScreenSelect={onScreenSelect}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function PrivacySubsection({
|
|
screen,
|
|
privacy,
|
|
onScreenSelect,
|
|
isPremiumRequired,
|
|
}: {
|
|
screen: SettingsScreens;
|
|
privacy?: ApiPrivacySettings;
|
|
isPremiumRequired?: boolean;
|
|
onScreenSelect: (screen: SettingsScreens) => void;
|
|
}) {
|
|
const { setPrivacyVisibility } = getActions();
|
|
const oldLang = useOldLang();
|
|
const lang = useLang();
|
|
|
|
const visibilityOptions = useMemo(() => {
|
|
const hasNobody = screen !== SettingsScreens.PrivacyAddByPhone;
|
|
const options = [
|
|
{ value: 'everybody', label: oldLang('P2PEverybody') },
|
|
{
|
|
value: 'contacts',
|
|
label: isPremiumRequired ? (
|
|
<PrivacyLockedOption label={oldLang('P2PContacts')} />
|
|
) : (
|
|
oldLang('P2PContacts')
|
|
),
|
|
hidden: isPremiumRequired,
|
|
},
|
|
];
|
|
|
|
if (hasNobody) {
|
|
options.push({
|
|
value: 'nobody',
|
|
label: isPremiumRequired ? (
|
|
<PrivacyLockedOption label={oldLang('P2PNobody')} />
|
|
) : (
|
|
oldLang('P2PNobody')
|
|
),
|
|
hidden: isPremiumRequired,
|
|
});
|
|
}
|
|
return options;
|
|
}, [oldLang, screen, isPremiumRequired]);
|
|
|
|
const primaryExceptionLists = useMemo(() => {
|
|
if (screen === SettingsScreens.PrivacyAddByPhone) {
|
|
return {
|
|
shouldShowDenied: false,
|
|
shouldShowAllowed: false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
shouldShowDenied: privacy?.visibility !== 'nobody',
|
|
shouldShowAllowed: privacy?.visibility !== 'everybody',
|
|
};
|
|
}, [privacy, screen]);
|
|
|
|
const privacyKey = getPrivacyKey(screen);
|
|
|
|
const descriptionText = useMemo(() => {
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyGifts:
|
|
return lang('PrivacyGiftsInfo');
|
|
case SettingsScreens.PrivacyLastSeen:
|
|
return oldLang('CustomHelp');
|
|
case SettingsScreens.PrivacyAddByPhone: {
|
|
return privacy?.visibility === 'everybody' ? oldLang('PrivacyPhoneInfo') : oldLang('PrivacyPhoneInfo3');
|
|
}
|
|
case SettingsScreens.PrivacyVoiceMessages:
|
|
return oldLang('PrivacyVoiceMessagesInfo');
|
|
default:
|
|
return undefined;
|
|
}
|
|
}, [oldLang, lang, screen, privacy]);
|
|
|
|
const headerText = useMemo(() => {
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyPhoneNumber:
|
|
return oldLang('PrivacyPhoneTitle');
|
|
case SettingsScreens.PrivacyAddByPhone:
|
|
return oldLang('PrivacyPhoneTitle2');
|
|
case SettingsScreens.PrivacyLastSeen:
|
|
return oldLang('LastSeenTitle');
|
|
case SettingsScreens.PrivacyProfilePhoto:
|
|
return oldLang('PrivacyProfilePhotoTitle');
|
|
case SettingsScreens.PrivacyBio:
|
|
return oldLang('PrivacyBioTitle');
|
|
case SettingsScreens.PrivacyBirthday:
|
|
return oldLang('PrivacyBirthdayTitle');
|
|
case SettingsScreens.PrivacyGifts:
|
|
return lang('PrivacyGiftsTitle');
|
|
case SettingsScreens.PrivacyForwarding:
|
|
return oldLang('PrivacyForwardsTitle');
|
|
case SettingsScreens.PrivacyVoiceMessages:
|
|
return oldLang('PrivacyVoiceMessagesTitle');
|
|
case SettingsScreens.PrivacyGroupChats:
|
|
return oldLang('WhoCanAddMe');
|
|
case SettingsScreens.PrivacyPhoneCall:
|
|
return oldLang('WhoCanCallMe');
|
|
case SettingsScreens.PrivacyPhoneP2P:
|
|
return oldLang('PrivacyP2P');
|
|
default:
|
|
return undefined;
|
|
}
|
|
}, [oldLang, lang, screen]);
|
|
|
|
const prepareSubtitle = useLastCallback(
|
|
(userIds?: string[], chatIds?: string[], shouldAllowPremium?: boolean, botsPrivacy?: BotsPrivacyType) => {
|
|
const userIdsCount = userIds?.length || 0;
|
|
const chatIdsCount = chatIds?.length || 0;
|
|
const isAllowBots = botsPrivacy === 'allow';
|
|
const hasPeers = userIdsCount || chatIdsCount;
|
|
|
|
if (!hasPeers && !isAllowBots) {
|
|
return shouldAllowPremium ? oldLang('PrivacyPremium') : oldLang('EditAdminAddUsers');
|
|
} else if (shouldAllowPremium) {
|
|
return oldLang('ContactsAndPremium');
|
|
}
|
|
|
|
const userCountString = userIdsCount > 0 ? oldLang('Users', userIdsCount) : undefined;
|
|
const chatCountString = chatIdsCount > 0 ? oldLang('Chats', chatIdsCount) : undefined;
|
|
|
|
const botPrivacyString = isAllowBots ? lang('PrivacyValueBots') : '';
|
|
const peersString = lang.conjunction([userCountString, chatCountString].filter(Boolean));
|
|
|
|
return [botPrivacyString, peersString].filter(Boolean).join(' ');
|
|
},
|
|
);
|
|
|
|
const allowedString = useMemo(() => {
|
|
return prepareSubtitle(
|
|
privacy?.allowUserIds,
|
|
privacy?.allowChatIds,
|
|
privacy?.shouldAllowPremium,
|
|
privacy?.botsPrivacy,
|
|
);
|
|
}, [privacy]);
|
|
|
|
const blockString = useMemo(() => {
|
|
return prepareSubtitle(privacy?.blockUserIds, privacy?.blockChatIds);
|
|
}, [privacy]);
|
|
|
|
const handleVisibilityChange = useCallback((value) => {
|
|
setPrivacyVisibility({
|
|
privacyKey: privacyKey!,
|
|
visibility: value,
|
|
});
|
|
}, [privacyKey]);
|
|
|
|
const allowedContactsScreen = (() => {
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyPhoneNumber:
|
|
return SettingsScreens.PrivacyPhoneNumberAllowedContacts;
|
|
case SettingsScreens.PrivacyLastSeen:
|
|
return SettingsScreens.PrivacyLastSeenAllowedContacts;
|
|
case SettingsScreens.PrivacyProfilePhoto:
|
|
return SettingsScreens.PrivacyProfilePhotoAllowedContacts;
|
|
case SettingsScreens.PrivacyBio:
|
|
return SettingsScreens.PrivacyBioAllowedContacts;
|
|
case SettingsScreens.PrivacyBirthday:
|
|
return SettingsScreens.PrivacyBirthdayAllowedContacts;
|
|
case SettingsScreens.PrivacyGifts:
|
|
return SettingsScreens.PrivacyGiftsAllowedContacts;
|
|
case SettingsScreens.PrivacyForwarding:
|
|
return SettingsScreens.PrivacyForwardingAllowedContacts;
|
|
case SettingsScreens.PrivacyPhoneCall:
|
|
return SettingsScreens.PrivacyPhoneCallAllowedContacts;
|
|
case SettingsScreens.PrivacyPhoneP2P:
|
|
return SettingsScreens.PrivacyPhoneP2PAllowedContacts;
|
|
case SettingsScreens.PrivacyVoiceMessages:
|
|
return SettingsScreens.PrivacyVoiceMessagesAllowedContacts;
|
|
default:
|
|
return SettingsScreens.PrivacyGroupChatsAllowedContacts;
|
|
}
|
|
})();
|
|
|
|
const deniedContactsScreen = (() => {
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyPhoneNumber:
|
|
return SettingsScreens.PrivacyPhoneNumberDeniedContacts;
|
|
case SettingsScreens.PrivacyLastSeen:
|
|
return SettingsScreens.PrivacyLastSeenDeniedContacts;
|
|
case SettingsScreens.PrivacyProfilePhoto:
|
|
return SettingsScreens.PrivacyProfilePhotoDeniedContacts;
|
|
case SettingsScreens.PrivacyBio:
|
|
return SettingsScreens.PrivacyBioDeniedContacts;
|
|
case SettingsScreens.PrivacyBirthday:
|
|
return SettingsScreens.PrivacyBirthdayDeniedContacts;
|
|
case SettingsScreens.PrivacyGifts:
|
|
return SettingsScreens.PrivacyGiftsDeniedContacts;
|
|
case SettingsScreens.PrivacyForwarding:
|
|
return SettingsScreens.PrivacyForwardingDeniedContacts;
|
|
case SettingsScreens.PrivacyPhoneCall:
|
|
return SettingsScreens.PrivacyPhoneCallDeniedContacts;
|
|
case SettingsScreens.PrivacyPhoneP2P:
|
|
return SettingsScreens.PrivacyPhoneP2PDeniedContacts;
|
|
case SettingsScreens.PrivacyVoiceMessages:
|
|
return SettingsScreens.PrivacyVoiceMessagesDeniedContacts;
|
|
default:
|
|
return SettingsScreens.PrivacyGroupChatsDeniedContacts;
|
|
}
|
|
})();
|
|
|
|
return (
|
|
<>
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>{headerText}</h4>
|
|
<RadioGroup
|
|
name={`visibility-${privacyKey}`}
|
|
options={visibilityOptions}
|
|
onChange={handleVisibilityChange}
|
|
selected={privacy?.visibility}
|
|
/>
|
|
{descriptionText && (
|
|
<p className="settings-item-description-larger" dir={oldLang.isRtl ? 'rtl' : undefined}>{descriptionText}</p>
|
|
)}
|
|
</div>
|
|
{!isPremiumRequired && (primaryExceptionLists.shouldShowAllowed || primaryExceptionLists.shouldShowDenied) && (
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
|
{oldLang('PrivacyExceptions')}
|
|
</h4>
|
|
{primaryExceptionLists.shouldShowAllowed && (
|
|
<ListItem
|
|
narrow
|
|
icon="add-user"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => {
|
|
onScreenSelect(allowedContactsScreen);
|
|
}}
|
|
>
|
|
<div className="multiline-item full-size">
|
|
<span className="title">{oldLang('AlwaysAllow')}</span>
|
|
<span className="subtitle">{allowedString}</span>
|
|
</div>
|
|
</ListItem>
|
|
)}
|
|
{primaryExceptionLists.shouldShowDenied && (
|
|
<ListItem
|
|
narrow
|
|
icon="delete-user"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => {
|
|
onScreenSelect(deniedContactsScreen);
|
|
}}
|
|
>
|
|
<div className="multiline-item full-size">
|
|
<span className="title">{oldLang('NeverAllow')}</span>
|
|
<span className="subtitle">{blockString}</span>
|
|
</div>
|
|
</ListItem>
|
|
)}
|
|
</div>
|
|
)}
|
|
{isPremiumRequired && <PremiumStatusItem />}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default memo(withGlobal<OwnProps>(
|
|
(global, { screen }): StateProps => {
|
|
let primaryPrivacy: ApiPrivacySettings | undefined;
|
|
let secondaryPrivacy: ApiPrivacySettings | undefined;
|
|
|
|
const {
|
|
currentUserId,
|
|
settings: { privacy },
|
|
} = global;
|
|
|
|
const currentUserFullInfo = selectUserFullInfo(global, currentUserId!);
|
|
|
|
switch (screen) {
|
|
case SettingsScreens.PrivacyPhoneNumber:
|
|
primaryPrivacy = privacy.phoneNumber;
|
|
secondaryPrivacy = privacy.addByPhone;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyLastSeen:
|
|
primaryPrivacy = privacy.lastSeen;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyProfilePhoto:
|
|
primaryPrivacy = privacy.profilePhoto;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyBio:
|
|
primaryPrivacy = privacy.bio;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyBirthday:
|
|
primaryPrivacy = privacy.birthday;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyGifts:
|
|
primaryPrivacy = privacy.gifts;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyPhoneP2P:
|
|
case SettingsScreens.PrivacyPhoneCall:
|
|
primaryPrivacy = privacy.phoneCall;
|
|
secondaryPrivacy = privacy.phoneP2P;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyForwarding:
|
|
primaryPrivacy = privacy.forwards;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyVoiceMessages:
|
|
primaryPrivacy = privacy.voiceMessages;
|
|
break;
|
|
|
|
case SettingsScreens.PrivacyGroupChats:
|
|
primaryPrivacy = privacy.chatInvite;
|
|
break;
|
|
}
|
|
|
|
if (!primaryPrivacy) {
|
|
return {
|
|
currentUserId: currentUserId!,
|
|
hasCurrentUserFullInfo: Boolean(currentUserFullInfo),
|
|
currentUserFallbackPhoto: currentUserFullInfo?.fallbackPhoto,
|
|
};
|
|
}
|
|
|
|
return {
|
|
primaryPrivacy,
|
|
secondaryPrivacy,
|
|
currentUserId: currentUserId!,
|
|
hasCurrentUserFullInfo: Boolean(currentUserFullInfo),
|
|
currentUserFallbackPhoto: currentUserFullInfo?.fallbackPhoto,
|
|
isPremiumRequired: screen === SettingsScreens.PrivacyVoiceMessages && !selectIsCurrentUserPremium(global),
|
|
};
|
|
},
|
|
)(SettingsPrivacyVisibility));
|