Privacy Gifts: Support settings (#5262)

This commit is contained in:
Alexander Zinchuk 2024-12-06 19:44:07 +04:00
parent 34b3df1ca6
commit 3603168978
17 changed files with 316 additions and 154 deletions

View File

@ -1,7 +1,7 @@
import { Api as GramJs } from '../../../lib/gramjs';
import { strippedPhotoToJpg } from '../../../lib/gramjs/Utils';
import type { ApiPrivacySettings, PrivacyVisibility } from '../../../types';
import type { ApiPrivacySettings, BotsPrivacyType, PrivacyVisibility } from '../../../types';
import type {
ApiFormattedText,
ApiMessageEntity,
@ -163,6 +163,7 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
let blockUserIds: string[] | undefined;
let blockChatIds: string[] | undefined;
let shouldAllowPremium: true | undefined;
let botsPrivacy: BotsPrivacyType = 'none';
const localChats = localDb.chats;
@ -198,6 +199,10 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
});
} else if (rule instanceof GramJs.PrivacyValueAllowPremium) {
shouldAllowPremium = true;
} else if (rule instanceof GramJs.PrivacyValueAllowBots) {
botsPrivacy = 'allow';
} else if (rule instanceof GramJs.PrivacyValueDisallowBots) {
botsPrivacy = 'disallow';
}
});
@ -215,6 +220,7 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
blockUserIds: blockUserIds || [],
blockChatIds: blockChatIds || [],
shouldAllowPremium,
botsPrivacy,
};
}

View File

@ -91,6 +91,8 @@ export function buildPrivacyKey(key: GramJs.TypePrivacyKey): ApiPrivacyKey | und
return 'bio';
case 'PrivacyKeyBirthday':
return 'birthday';
case 'PrivacyKeyStarGiftsAutoSave':
return 'gifts';
}
return undefined;

View File

@ -466,6 +466,9 @@ export function buildInputPrivacyKey(privacyKey: ApiPrivacyKey) {
case 'birthday':
return new GramJs.InputPrivacyKeyBirthday();
case 'gifts':
return new GramJs.InputPrivacyKeyStarGiftsAutoSave();
}
return undefined;
@ -800,6 +803,14 @@ export function buildInputPrivacyRules(
privacyRules.push(new GramJs.InputPrivacyValueAllowPremium());
}
if (rules.botsPrivacy === 'allow') {
privacyRules.push(new GramJs.InputPrivacyValueAllowBots());
}
if (rules.botsPrivacy === 'disallow') {
privacyRules.push(new GramJs.InputPrivacyValueDisallowBots());
}
if (!rules.isUnspecified) {
switch (rules.visibility) {
case 'everybody':

View File

@ -1393,6 +1393,11 @@
"BotSuggestedStatus" = "Do you want to set this emoji status suggested by **{bot}**?";
"BotSuggestedStatusTitle" = "Set Emoji Status";
"BotSuggestedStatusUpdated" = "Your emoji status is updated.";
"PrivacyGifts" = "Gifts";
"PrivacyGiftsTitle" = "Who can display gifts on my profile?"
"PrivacyGiftsInfo" = "Choose whether gifts from specific senders need your approval before they're visible to others on your profile."
"PrivacyValueBots" = "Mini Apps"
"CustomShareGiftsInfo" = "You can add users or entire groups as exceptions that will override the settings above."
"StarsSubscribeBotText_one" = "Do you want to subscribe to **{name}** in **{bot}** for **{amount}** star per month?"
"StarsSubscribeBotText_other" = "Do you want to subscribe to **{name}** in **{bot}** for **{amount}** stars per month?"
"StarsSubscribeBotButtonMonth" = "Subscribe for {amount} / month";

View File

@ -192,6 +192,7 @@ function LeftColumn({
case SettingsScreens.PrivacyProfilePhoto:
case SettingsScreens.PrivacyBio:
case SettingsScreens.PrivacyBirthday:
case SettingsScreens.PrivacyGifts:
case SettingsScreens.PrivacyPhoneCall:
case SettingsScreens.PrivacyPhoneP2P:
case SettingsScreens.PrivacyForwarding:
@ -250,6 +251,10 @@ function LeftColumn({
case SettingsScreens.PrivacyBirthdayDeniedContacts:
setSettingsScreen(SettingsScreens.PrivacyBirthday);
return;
case SettingsScreens.PrivacyGiftsAllowedContacts:
case SettingsScreens.PrivacyGiftsDeniedContacts:
setSettingsScreen(SettingsScreens.PrivacyGifts);
return;
case SettingsScreens.PrivacyPhoneCallAllowedContacts:
case SettingsScreens.PrivacyPhoneCallDeniedContacts:
setSettingsScreen(SettingsScreens.PrivacyPhoneCall);

View File

@ -110,6 +110,11 @@ const PRIVACY_BIRTHDAY_SCREENS = [
SettingsScreens.PrivacyBirthdayDeniedContacts,
];
const PRIVACY_GIFTS_SCREENS = [
SettingsScreens.PrivacyGiftsAllowedContacts,
SettingsScreens.PrivacyGiftsDeniedContacts,
];
const PRIVACY_PHONE_CALL_SCREENS = [
SettingsScreens.PrivacyPhoneCallAllowedContacts,
SettingsScreens.PrivacyPhoneCallDeniedContacts,
@ -204,6 +209,7 @@ const Settings: FC<OwnProps> = ({
[SettingsScreens.PrivacyProfilePhoto]: PRIVACY_PROFILE_PHOTO_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyBio]: PRIVACY_BIO_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyBirthday]: PRIVACY_BIRTHDAY_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyGifts]: PRIVACY_GIFTS_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyPhoneCall]: PRIVACY_PHONE_CALL_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyPhoneP2P]: PRIVACY_PHONE_P2P_SCREENS.includes(activeScreen),
[SettingsScreens.PrivacyForwarding]: PRIVACY_FORWARDING_SCREENS.includes(activeScreen),
@ -330,6 +336,7 @@ const Settings: FC<OwnProps> = ({
case SettingsScreens.PrivacyProfilePhoto:
case SettingsScreens.PrivacyBio:
case SettingsScreens.PrivacyBirthday:
case SettingsScreens.PrivacyGifts:
case SettingsScreens.PrivacyPhoneCall:
case SettingsScreens.PrivacyForwarding:
case SettingsScreens.PrivacyVoiceMessages:
@ -348,6 +355,7 @@ const Settings: FC<OwnProps> = ({
case SettingsScreens.PrivacyProfilePhotoAllowedContacts:
case SettingsScreens.PrivacyBioAllowedContacts:
case SettingsScreens.PrivacyBirthdayAllowedContacts:
case SettingsScreens.PrivacyGiftsAllowedContacts:
case SettingsScreens.PrivacyPhoneCallAllowedContacts:
case SettingsScreens.PrivacyPhoneP2PAllowedContacts:
case SettingsScreens.PrivacyForwardingAllowedContacts:
@ -357,6 +365,7 @@ const Settings: FC<OwnProps> = ({
<SettingsPrivacyVisibilityExceptionList
isAllowList
withPremiumCategory={currentScreen === SettingsScreens.PrivacyGroupChatsAllowedContacts}
withMiniAppsCategory={currentScreen === SettingsScreens.PrivacyGiftsAllowedContacts}
screen={currentScreen}
onScreenSelect={onScreenSelect}
isActive={isScreenActive || privacyAllowScreens[currentScreen]}
@ -369,6 +378,7 @@ const Settings: FC<OwnProps> = ({
case SettingsScreens.PrivacyProfilePhotoDeniedContacts:
case SettingsScreens.PrivacyBioDeniedContacts:
case SettingsScreens.PrivacyBirthdayDeniedContacts:
case SettingsScreens.PrivacyGiftsDeniedContacts:
case SettingsScreens.PrivacyPhoneCallDeniedContacts:
case SettingsScreens.PrivacyPhoneP2PDeniedContacts:
case SettingsScreens.PrivacyForwardingDeniedContacts:

View File

@ -7,6 +7,7 @@ import { getActions } from '../../../global';
import { SettingsScreens } from '../../../types';
import useAppLayout from '../../../hooks/useAppLayout';
import useLang from '../../../hooks/useLang';
import useMultiClick from '../../../hooks/useMultiClick';
import useOldLang from '../../../hooks/useOldLang';
@ -75,146 +76,151 @@ const SettingsHeader: FC<OwnProps> = ({
);
}, [isMobile]);
const lang = useOldLang();
const oldLang = useOldLang();
const lang = useLang();
function renderHeaderContent() {
switch (currentScreen) {
case SettingsScreens.EditProfile:
return <h3>{lang('lng_settings_information')}</h3>;
return <h3>{oldLang('lng_settings_information')}</h3>;
case SettingsScreens.General:
return <h3>{lang('General')}</h3>;
return <h3>{oldLang('General')}</h3>;
case SettingsScreens.QuickReaction:
return <h3>{lang('DoubleTapSetting')}</h3>;
return <h3>{oldLang('DoubleTapSetting')}</h3>;
case SettingsScreens.CustomEmoji:
return <h3>{lang('Emoji')}</h3>;
return <h3>{oldLang('Emoji')}</h3>;
case SettingsScreens.Notifications:
return <h3>{lang('Notifications')}</h3>;
return <h3>{oldLang('Notifications')}</h3>;
case SettingsScreens.DataStorage:
return <h3>{lang('DataSettings')}</h3>;
return <h3>{oldLang('DataSettings')}</h3>;
case SettingsScreens.Privacy:
return <h3>{lang('PrivacySettings')}</h3>;
return <h3>{oldLang('PrivacySettings')}</h3>;
case SettingsScreens.Language:
return <h3>{lang('Language')}</h3>;
return <h3>{oldLang('Language')}</h3>;
case SettingsScreens.DoNotTranslate:
return <h3>{lang('DoNotTranslate')}</h3>;
return <h3>{oldLang('DoNotTranslate')}</h3>;
case SettingsScreens.Stickers:
return <h3>{lang('StickersName')}</h3>;
return <h3>{oldLang('StickersName')}</h3>;
case SettingsScreens.Experimental:
return <h3>{lang('lng_settings_experimental')}</h3>;
return <h3>{oldLang('lng_settings_experimental')}</h3>;
case SettingsScreens.GeneralChatBackground:
return <h3>{lang('ChatBackground')}</h3>;
return <h3>{oldLang('ChatBackground')}</h3>;
case SettingsScreens.GeneralChatBackgroundColor:
return <h3>{lang('SetColor')}</h3>;
return <h3>{oldLang('SetColor')}</h3>;
case SettingsScreens.PrivacyPhoneNumber:
return <h3>{lang('PrivacyPhone')}</h3>;
return <h3>{oldLang('PrivacyPhone')}</h3>;
case SettingsScreens.PrivacyLastSeen:
return <h3>{lang('PrivacyLastSeen')}</h3>;
return <h3>{oldLang('PrivacyLastSeen')}</h3>;
case SettingsScreens.PrivacyProfilePhoto:
return <h3>{lang('Privacy.ProfilePhoto')}</h3>;
return <h3>{oldLang('Privacy.ProfilePhoto')}</h3>;
case SettingsScreens.PrivacyBio:
return <h3>{lang('PrivacyBio')}</h3>;
return <h3>{oldLang('PrivacyBio')}</h3>;
case SettingsScreens.PrivacyBirthday:
return <h3>{lang('PrivacyBirthday')}</h3>;
return <h3>{oldLang('PrivacyBirthday')}</h3>;
case SettingsScreens.PrivacyGifts:
return <h3>{lang('PrivacyGifts')}</h3>;
case SettingsScreens.PrivacyForwarding:
return <h3>{lang('PrivacyForwards')}</h3>;
return <h3>{oldLang('PrivacyForwards')}</h3>;
case SettingsScreens.PrivacyVoiceMessages:
return <h3>{lang('PrivacyVoiceMessages')}</h3>;
return <h3>{oldLang('PrivacyVoiceMessages')}</h3>;
case SettingsScreens.PrivacyMessages:
return <h3>{lang('PrivacyMessages')}</h3>;
return <h3>{oldLang('PrivacyMessages')}</h3>;
case SettingsScreens.PrivacyGroupChats:
return <h3>{lang('AutodownloadGroupChats')}</h3>;
return <h3>{oldLang('AutodownloadGroupChats')}</h3>;
case SettingsScreens.PrivacyPhoneCall:
return <h3>{lang('Calls')}</h3>;
return <h3>{oldLang('Calls')}</h3>;
case SettingsScreens.PrivacyPhoneNumberAllowedContacts:
case SettingsScreens.PrivacyLastSeenAllowedContacts:
case SettingsScreens.PrivacyProfilePhotoAllowedContacts:
case SettingsScreens.PrivacyBioAllowedContacts:
case SettingsScreens.PrivacyBirthdayAllowedContacts:
case SettingsScreens.PrivacyGiftsAllowedContacts:
case SettingsScreens.PrivacyForwardingAllowedContacts:
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
case SettingsScreens.PrivacyPhoneCallAllowedContacts:
case SettingsScreens.PrivacyPhoneP2PAllowedContacts:
return <h3>{lang('AlwaysShareWith')}</h3>;
return <h3>{oldLang('AlwaysShareWith')}</h3>;
case SettingsScreens.PrivacyPhoneNumberDeniedContacts:
case SettingsScreens.PrivacyLastSeenDeniedContacts:
case SettingsScreens.PrivacyProfilePhotoDeniedContacts:
case SettingsScreens.PrivacyBioDeniedContacts:
case SettingsScreens.PrivacyBirthdayDeniedContacts:
case SettingsScreens.PrivacyGiftsDeniedContacts:
case SettingsScreens.PrivacyForwardingDeniedContacts:
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
case SettingsScreens.PrivacyPhoneCallDeniedContacts:
case SettingsScreens.PrivacyPhoneP2PDeniedContacts:
return <h3>{lang('NeverShareWith')}</h3>;
return <h3>{oldLang('NeverShareWith')}</h3>;
case SettingsScreens.Performance:
return <h3>{lang('Animations and Performance')}</h3>;
return <h3>{oldLang('Animations and Performance')}</h3>;
case SettingsScreens.ActiveSessions:
return <h3>{lang('SessionsTitle')}</h3>;
return <h3>{oldLang('SessionsTitle')}</h3>;
case SettingsScreens.ActiveWebsites:
return <h3>{lang('OtherWebSessions')}</h3>;
return <h3>{oldLang('OtherWebSessions')}</h3>;
case SettingsScreens.PrivacyBlockedUsers:
return <h3>{lang('BlockedUsers')}</h3>;
return <h3>{oldLang('BlockedUsers')}</h3>;
case SettingsScreens.TwoFaDisabled:
case SettingsScreens.TwoFaEnabled:
return <h3>{lang('TwoStepVerification')}</h3>;
return <h3>{oldLang('TwoStepVerification')}</h3>;
case SettingsScreens.TwoFaNewPassword:
case SettingsScreens.TwoFaChangePasswordNew:
case SettingsScreens.TwoFaChangePasswordConfirm:
return <h3>{lang('PleaseEnterCurrentPassword')}</h3>;
return <h3>{oldLang('PleaseEnterCurrentPassword')}</h3>;
case SettingsScreens.TwoFaNewPasswordConfirm:
return <h3>{lang('PleaseReEnterPassword')}</h3>;
return <h3>{oldLang('PleaseReEnterPassword')}</h3>;
case SettingsScreens.TwoFaNewPasswordHint:
case SettingsScreens.TwoFaChangePasswordHint:
return <h3>{lang('PasswordHint')}</h3>;
return <h3>{oldLang('PasswordHint')}</h3>;
case SettingsScreens.TwoFaNewPasswordEmail:
case SettingsScreens.TwoFaRecoveryEmail:
return <h3>{lang('RecoveryEmailTitle')}</h3>;
return <h3>{oldLang('RecoveryEmailTitle')}</h3>;
case SettingsScreens.TwoFaNewPasswordEmailCode:
case SettingsScreens.TwoFaRecoveryEmailCode:
return <h3>Recovery Email Code</h3>;
case SettingsScreens.TwoFaCongratulations:
return <h3>{lang('TwoStepVerificationPasswordSet')}</h3>;
return <h3>{oldLang('TwoStepVerificationPasswordSet')}</h3>;
case SettingsScreens.TwoFaChangePasswordCurrent:
case SettingsScreens.TwoFaTurnOff:
case SettingsScreens.TwoFaRecoveryEmailCurrentPassword:
return <h3>{lang('PleaseEnterCurrentPassword')}</h3>;
return <h3>{oldLang('PleaseEnterCurrentPassword')}</h3>;
case SettingsScreens.PasscodeDisabled:
case SettingsScreens.PasscodeEnabled:
case SettingsScreens.PasscodeNewPasscode:
case SettingsScreens.PasscodeNewPasscodeConfirm:
case SettingsScreens.PasscodeCongratulations:
return <h3>{lang('Passcode')}</h3>;
return <h3>{oldLang('Passcode')}</h3>;
case SettingsScreens.PasscodeTurnOff:
return <h3>{lang('PasscodeController.Disable.Title')}</h3>;
return <h3>{oldLang('PasscodeController.Disable.Title')}</h3>;
case SettingsScreens.PasscodeChangePasscodeCurrent:
case SettingsScreens.PasscodeChangePasscodeNew:
return <h3>{lang('PasscodeController.Change.Title')}</h3>;
return <h3>{oldLang('PasscodeController.Change.Title')}</h3>;
case SettingsScreens.PasscodeChangePasscodeConfirm:
return <h3>{lang('PasscodeController.ReEnterPasscode.Placeholder')}</h3>;
return <h3>{oldLang('PasscodeController.ReEnterPasscode.Placeholder')}</h3>;
case SettingsScreens.Folders:
return <h3>{lang('Filters')}</h3>;
return <h3>{oldLang('Filters')}</h3>;
case SettingsScreens.FoldersCreateFolder:
return <h3>{lang('FilterNew')}</h3>;
return <h3>{oldLang('FilterNew')}</h3>;
case SettingsScreens.FoldersShare:
return <h3>{lang('FolderLinkScreen.Title')}</h3>;
return <h3>{oldLang('FolderLinkScreen.Title')}</h3>;
case SettingsScreens.FoldersEditFolder:
case SettingsScreens.FoldersEditFolderFromChatList:
case SettingsScreens.FoldersEditFolderInvites:
return (
<div className="settings-main-header">
<h3>{lang('FilterEdit')}</h3>
<h3>{oldLang('FilterEdit')}</h3>
{Boolean(editedFolderId) && (
<DropdownMenu
className="settings-more-menu"
@ -222,7 +228,7 @@ const SettingsHeader: FC<OwnProps> = ({
positionX="right"
>
<MenuItem icon="delete" destructive onClick={openDeleteFolderConfirmation}>
{lang('Delete')}
{oldLang('Delete')}
</MenuItem>
</DropdownMenu>
)}
@ -234,7 +240,7 @@ const SettingsHeader: FC<OwnProps> = ({
case SettingsScreens.FoldersExcludedChatsFromChatList:
return (
<h3>
{lang(
{oldLang(
currentScreen === SettingsScreens.FoldersIncludedChats
|| currentScreen === SettingsScreens.FoldersIncludedChatsFromChatList
? 'FilterInclude' : 'FilterExclude',
@ -246,7 +252,7 @@ const SettingsHeader: FC<OwnProps> = ({
<div className="settings-main-header">
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
<h3 onClick={handleMultiClick}>
{lang('SETTINGS')}
{oldLang('SETTINGS')}
</h3>
<Button
@ -256,7 +262,7 @@ const SettingsHeader: FC<OwnProps> = ({
color="translucent"
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onScreenSelect(SettingsScreens.EditProfile)}
ariaLabel={lang('lng_settings_information')}
ariaLabel={oldLang('lng_settings_information')}
>
<i className="icon icon-edit" />
</Button>
@ -265,7 +271,7 @@ const SettingsHeader: FC<OwnProps> = ({
trigger={SettingsMenuButton}
positionX="right"
>
<MenuItem icon="logout" onClick={openSignOutConfirmation}>{lang('LogOutTitle')}</MenuItem>
<MenuItem icon="logout" onClick={openSignOutConfirmation}>{oldLang('LogOutTitle')}</MenuItem>
</DropdownMenu>
</div>
);
@ -279,7 +285,7 @@ const SettingsHeader: FC<OwnProps> = ({
size="smaller"
color="translucent"
onClick={onReset}
ariaLabel={lang('AccDescrGoBack')}
ariaLabel={oldLang('AccDescrGoBack')}
>
<i className="icon icon-arrow-left" />
</Button>
@ -287,8 +293,8 @@ const SettingsHeader: FC<OwnProps> = ({
<ConfirmDialog
isOpen={isSignOutDialogOpen}
onClose={closeSignOutConfirmation}
text={lang('lng_sure_logout')}
confirmLabel={lang('AccountSettings.Logout')}
text={oldLang('lng_sure_logout')}
confirmLabel={oldLang('AccountSettings.Logout')}
confirmHandler={handleSignOutMessage}
confirmIsDestructive
/>

View File

@ -9,6 +9,7 @@ import { SettingsScreens } from '../../../types';
import { selectCanSetPasscode, selectIsCurrentUserPremium } from '../../../global/selectors';
import useHistoryBack from '../../../hooks/useHistoryBack';
import useLang from '../../../hooks/useLang';
import useOldLang from '../../../hooks/useOldLang';
import StarIcon from '../../common/icons/StarIcon';
@ -79,7 +80,8 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
}
}, [isActive, loadGlobalPrivacySettings]);
const lang = useOldLang();
const oldLang = useOldLang();
const lang = useLang();
useHistoryBack({
isActive,
@ -103,30 +105,39 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
}, [updateContentSettings]);
function getVisibilityValue(setting?: ApiPrivacySettings) {
if (!setting) return lang('Loading');
if (!setting) return oldLang('Loading');
const { visibility, shouldAllowPremium, botsPrivacy } = setting;
const isAllowBots = botsPrivacy === 'allow';
const isVisibilityEverybody = visibility === 'everybody';
const shouldShowBotsString = isAllowBots && !isVisibilityEverybody;
const { visibility, shouldAllowPremium } = setting;
const blockCount = setting.blockChatIds.length + setting.blockUserIds.length;
const allowCount = setting.allowChatIds.length + setting.allowUserIds.length;
const total = [];
if (blockCount) total.push(`-${blockCount}`);
if (allowCount) total.push(`+${allowCount}`);
if (allowCount && !isVisibilityEverybody) total.push(`+${allowCount}`);
const exceptionString = total.length ? `(${total.join(',')})` : '';
const botPrivacyString = shouldShowBotsString ? lang('PrivacyValueBots') : '';
const totalString = lang.conjunction(total);
const exceptionString = [botPrivacyString, totalString].filter(Boolean).join(' ');
if (shouldShowBotsString && !isVisibilityEverybody) return exceptionString;
if (shouldAllowPremium) {
return lang(exceptionString ? 'ContactsAndPremium' : 'PrivacyPremium');
return oldLang(exceptionString ? 'ContactsAndPremium' : 'PrivacyPremium');
}
switch (visibility) {
case 'everybody':
return `${lang('P2PEverybody')} ${exceptionString}`;
return `${oldLang('P2PEverybody')} ${exceptionString}`;
case 'contacts':
return `${lang('P2PContacts')} ${exceptionString}`;
return `${oldLang('P2PContacts')} ${exceptionString}`;
case 'nobody':
return `${lang('P2PNobody')} ${exceptionString}`;
return `${oldLang('P2PNobody')} ${exceptionString}`;
}
return undefined;
@ -141,7 +152,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onScreenSelect(SettingsScreens.PrivacyBlockedUsers)}
>
{lang('BlockedUsers')}
{oldLang('BlockedUsers')}
<span className="settings-item__current-value">{blockedCount || ''}</span>
</ListItem>
{canSetPasscode && (
@ -154,9 +165,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
)}
>
<div className="multiline-menu-item">
<span className="title">{lang('Passcode')}</span>
<span className="title">{oldLang('Passcode')}</span>
<span className="subtitle" dir="auto">
{lang(hasPasscode ? 'PasswordOn' : 'PasswordOff')}
{oldLang(hasPasscode ? 'PasswordOn' : 'PasswordOff')}
</span>
</div>
</ListItem>
@ -170,9 +181,9 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
)}
>
<div className="multiline-menu-item">
<span className="title">{lang('TwoStepVerification')}</span>
<span className="title">{oldLang('TwoStepVerification')}</span>
<span className="subtitle" dir="auto">
{lang(hasPassword ? 'PasswordOn' : 'PasswordOff')}
{oldLang(hasPassword ? 'PasswordOn' : 'PasswordOff')}
</span>
</div>
</ListItem>
@ -183,14 +194,14 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onScreenSelect(SettingsScreens.ActiveWebsites)}
>
{lang('PrivacySettings.WebSessions')}
{oldLang('PrivacySettings.WebSessions')}
<span className="settings-item__current-value">{webAuthCount}</span>
</ListItem>
)}
</div>
<div className="settings-item">
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('PrivacyTitle')}</h4>
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>{oldLang('PrivacyTitle')}</h4>
<ListItem
narrow
@ -199,7 +210,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneNumber)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyPhoneTitle')}</span>
<span className="title">{oldLang('PrivacyPhoneTitle')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.phoneNumber)}
</span>
@ -212,7 +223,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyLastSeen)}
>
<div className="multiline-menu-item">
<span className="title">{lang('LastSeenTitle')}</span>
<span className="title">{oldLang('LastSeenTitle')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.lastSeen)}
</span>
@ -225,7 +236,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyProfilePhoto)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyProfilePhotoTitle')}</span>
<span className="title">{oldLang('PrivacyProfilePhotoTitle')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.profilePhoto)}
</span>
@ -238,7 +249,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyBio)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyBio')}</span>
<span className="title">{oldLang('PrivacyBio')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.bio)}
</span>
@ -251,12 +262,25 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyBirthday)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyBirthday')}</span>
<span className="title">{oldLang('PrivacyBirthday')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.birthday)}
</span>
</div>
</ListItem>
<ListItem
narrow
className="no-icon"
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onScreenSelect(SettingsScreens.PrivacyGifts)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyGifts')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.gifts)}
</span>
</div>
</ListItem>
<ListItem
narrow
className="no-icon"
@ -264,7 +288,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyForwarding)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyForwardsTitle')}</span>
<span className="title">{oldLang('PrivacyForwardsTitle')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.forwards)}
</span>
@ -277,7 +301,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneCall)}
>
<div className="multiline-menu-item">
<span className="title">{lang('WhoCanCallMe')}</span>
<span className="title">{oldLang('WhoCanCallMe')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.phoneCall)}
</span>
@ -292,7 +316,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyVoiceMessages)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyVoiceMessagesTitle')}</span>
<span className="title">{oldLang('PrivacyVoiceMessagesTitle')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.voiceMessages)}
</span>
@ -306,11 +330,11 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyMessages)}
>
<div className="multiline-menu-item">
<span className="title">{lang('PrivacyMessagesTitle')}</span>
<span className="title">{oldLang('PrivacyMessagesTitle')}</span>
<span className="subtitle" dir="auto">
{shouldNewNonContactPeersRequirePremium
? lang('PrivacyMessagesContactsAndPremium')
: lang('P2PEverybody')}
? oldLang('PrivacyMessagesContactsAndPremium')
: oldLang('P2PEverybody')}
</span>
</div>
</ListItem>
@ -321,7 +345,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
onClick={() => onScreenSelect(SettingsScreens.PrivacyGroupChats)}
>
<div className="multiline-menu-item">
<span className="title">{lang('WhoCanAddMe')}</span>
<span className="title">{oldLang('WhoCanAddMe')}</span>
<span className="subtitle" dir="auto">
{getVisibilityValue(privacy.chatInvite)}
</span>
@ -331,12 +355,12 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
{canChangeSensitive && (
<div className="settings-item">
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
{lang('lng_settings_sensitive_title')}
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
{oldLang('lng_settings_sensitive_title')}
</h4>
<Checkbox
label={lang('lng_settings_sensitive_disable_filtering')}
subLabel={lang('lng_settings_sensitive_about')}
label={oldLang('lng_settings_sensitive_disable_filtering')}
subLabel={oldLang('lng_settings_sensitive_about')}
checked={Boolean(isSensitiveEnabled)}
disabled={!canChangeSensitive}
onCheck={handleUpdateContentSettings}
@ -346,12 +370,12 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
{canDisplayAutoarchiveSetting && (
<div className="settings-item">
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
{lang('NewChatsFromNonContacts')}
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
{oldLang('NewChatsFromNonContacts')}
</h4>
<Checkbox
label={lang('ArchiveAndMute')}
subLabel={lang('ArchiveAndMuteInfo')}
label={oldLang('ArchiveAndMute')}
subLabel={oldLang('ArchiveAndMuteInfo')}
checked={Boolean(shouldArchiveAndMuteNewNonContact)}
onCheck={handleArchiveAndMuteChange}
/>
@ -359,11 +383,11 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
)}
<div className="settings-item">
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
{lang('lng_settings_window_system')}
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
{oldLang('lng_settings_window_system')}
</h4>
<Checkbox
label={lang('lng_settings_title_chat_name')}
label={oldLang('lng_settings_title_chat_name')}
checked={Boolean(canDisplayChatInTitle)}
onCheck={handleChatInTitleChange}
/>

View File

@ -3,13 +3,14 @@ import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiPhoto } from '../../../api/types';
import type { ApiPrivacySettings } from '../../../types';
import type { ApiPrivacySettings, BotsPrivacyType } from '../../../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';
@ -106,18 +107,19 @@ function PrivacySubsection({
onScreenSelect: (screen: SettingsScreens) => void;
}) {
const { setPrivacyVisibility } = getActions();
const lang = useOldLang();
const oldLang = useOldLang();
const lang = useLang();
const visibilityOptions = useMemo(() => {
const hasNobody = screen !== SettingsScreens.PrivacyAddByPhone;
const options = [
{ value: 'everybody', label: lang('P2PEverybody') },
{ value: 'everybody', label: oldLang('P2PEverybody') },
{
value: 'contacts',
label: isPremiumRequired ? (
<PrivacyLockedOption label={lang('P2PContacts')} />
<PrivacyLockedOption label={oldLang('P2PContacts')} />
) : (
lang('P2PContacts')
oldLang('P2PContacts')
),
hidden: isPremiumRequired,
},
@ -127,15 +129,15 @@ function PrivacySubsection({
options.push({
value: 'nobody',
label: isPremiumRequired ? (
<PrivacyLockedOption label={lang('P2PNobody')} />
<PrivacyLockedOption label={oldLang('P2PNobody')} />
) : (
lang('P2PNobody')
oldLang('P2PNobody')
),
hidden: isPremiumRequired,
});
}
return options;
}, [lang, screen, isPremiumRequired]);
}, [oldLang, screen, isPremiumRequired]);
const primaryExceptionLists = useMemo(() => {
if (screen === SettingsScreens.PrivacyAddByPhone) {
@ -155,65 +157,81 @@ function PrivacySubsection({
const descriptionText = useMemo(() => {
switch (screen) {
case SettingsScreens.PrivacyGifts:
return lang('PrivacyGiftsInfo');
case SettingsScreens.PrivacyLastSeen:
return lang('CustomHelp');
return oldLang('CustomHelp');
case SettingsScreens.PrivacyAddByPhone: {
return privacy?.visibility === 'everybody' ? lang('PrivacyPhoneInfo') : lang('PrivacyPhoneInfo3');
return privacy?.visibility === 'everybody' ? oldLang('PrivacyPhoneInfo') : oldLang('PrivacyPhoneInfo3');
}
case SettingsScreens.PrivacyVoiceMessages:
return lang('PrivacyVoiceMessagesInfo');
return oldLang('PrivacyVoiceMessagesInfo');
default:
return undefined;
}
}, [lang, screen, privacy]);
}, [oldLang, lang, screen, privacy]);
const headerText = useMemo(() => {
switch (screen) {
case SettingsScreens.PrivacyPhoneNumber:
return lang('PrivacyPhoneTitle');
return oldLang('PrivacyPhoneTitle');
case SettingsScreens.PrivacyAddByPhone:
return lang('PrivacyPhoneTitle2');
return oldLang('PrivacyPhoneTitle2');
case SettingsScreens.PrivacyLastSeen:
return lang('LastSeenTitle');
return oldLang('LastSeenTitle');
case SettingsScreens.PrivacyProfilePhoto:
return lang('PrivacyProfilePhotoTitle');
return oldLang('PrivacyProfilePhotoTitle');
case SettingsScreens.PrivacyBio:
return lang('PrivacyBioTitle');
return oldLang('PrivacyBioTitle');
case SettingsScreens.PrivacyBirthday:
return lang('PrivacyBirthdayTitle');
return oldLang('PrivacyBirthdayTitle');
case SettingsScreens.PrivacyGifts:
return lang('PrivacyGiftsTitle');
case SettingsScreens.PrivacyForwarding:
return lang('PrivacyForwardsTitle');
return oldLang('PrivacyForwardsTitle');
case SettingsScreens.PrivacyVoiceMessages:
return lang('PrivacyVoiceMessagesTitle');
return oldLang('PrivacyVoiceMessagesTitle');
case SettingsScreens.PrivacyGroupChats:
return lang('WhoCanAddMe');
return oldLang('WhoCanAddMe');
case SettingsScreens.PrivacyPhoneCall:
return lang('WhoCanCallMe');
return oldLang('WhoCanCallMe');
case SettingsScreens.PrivacyPhoneP2P:
return lang('PrivacyP2P');
return oldLang('PrivacyP2P');
default:
return undefined;
}
}, [lang, screen]);
}, [oldLang, lang, screen]);
const prepareSubtitle = useLastCallback((userIds?: string[], chatIds?: string[], shouldAllowPremium?: boolean) => {
const userIdsCount = userIds?.length || 0;
const chatIdsCount = chatIds?.length || 0;
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 (!userIdsCount && !chatIdsCount) {
return shouldAllowPremium ? lang('PrivacyPremium') : lang('EditAdminAddUsers');
} else if (shouldAllowPremium) {
return lang('ContactsAndPremium');
}
if (!hasPeers && !isAllowBots) {
return shouldAllowPremium ? oldLang('PrivacyPremium') : oldLang('EditAdminAddUsers');
} else if (shouldAllowPremium) {
return oldLang('ContactsAndPremium');
}
const userCountString = userIdsCount > 0 ? lang('Users', userIdsCount) : undefined;
const chatCountString = chatIdsCount > 0 ? lang('Chats', chatIdsCount) : undefined;
const userCountString = userIdsCount > 0 ? oldLang('Users', userIdsCount) : undefined;
const chatCountString = chatIdsCount > 0 ? oldLang('Chats', chatIdsCount) : undefined;
return [userCountString, chatCountString].filter(Boolean).join(', ');
});
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);
return prepareSubtitle(
privacy?.allowUserIds,
privacy?.allowChatIds,
privacy?.shouldAllowPremium,
privacy?.botsPrivacy,
);
}, [privacy]);
const blockString = useMemo(() => {
@ -239,6 +257,8 @@ function PrivacySubsection({
return SettingsScreens.PrivacyBioAllowedContacts;
case SettingsScreens.PrivacyBirthday:
return SettingsScreens.PrivacyBirthdayAllowedContacts;
case SettingsScreens.PrivacyGifts:
return SettingsScreens.PrivacyGiftsAllowedContacts;
case SettingsScreens.PrivacyForwarding:
return SettingsScreens.PrivacyForwardingAllowedContacts;
case SettingsScreens.PrivacyPhoneCall:
@ -264,6 +284,8 @@ function PrivacySubsection({
return SettingsScreens.PrivacyBioDeniedContacts;
case SettingsScreens.PrivacyBirthday:
return SettingsScreens.PrivacyBirthdayDeniedContacts;
case SettingsScreens.PrivacyGifts:
return SettingsScreens.PrivacyGiftsDeniedContacts;
case SettingsScreens.PrivacyForwarding:
return SettingsScreens.PrivacyForwardingDeniedContacts;
case SettingsScreens.PrivacyPhoneCall:
@ -280,7 +302,7 @@ function PrivacySubsection({
return (
<>
<div className="settings-item">
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{headerText}</h4>
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>{headerText}</h4>
<RadioGroup
name={`visibility-${privacyKey}`}
options={visibilityOptions}
@ -288,13 +310,13 @@ function PrivacySubsection({
selected={privacy?.visibility}
/>
{descriptionText && (
<p className="settings-item-description-larger" dir={lang.isRtl ? 'rtl' : undefined}>{descriptionText}</p>
<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={lang.isRtl ? 'rtl' : undefined}>
{lang('PrivacyExceptions')}
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
{oldLang('PrivacyExceptions')}
</h4>
{primaryExceptionLists.shouldShowAllowed && (
<ListItem
@ -306,7 +328,7 @@ function PrivacySubsection({
}}
>
<div className="multiline-menu-item full-size">
<span className="title">{lang('AlwaysAllow')}</span>
<span className="title">{oldLang('AlwaysAllow')}</span>
<span className="subtitle">{allowedString}</span>
</div>
</ListItem>
@ -321,7 +343,7 @@ function PrivacySubsection({
}}
>
<div className="multiline-menu-item full-size">
<span className="title">{lang('NeverAllow')}</span>
<span className="title">{oldLang('NeverAllow')}</span>
<span className="subtitle">{blockString}</span>
</div>
</ListItem>
@ -367,6 +389,10 @@ export default memo(withGlobal<OwnProps>(
primaryPrivacy = privacy.birthday;
break;
case SettingsScreens.PrivacyGifts:
primaryPrivacy = privacy.gifts;
break;
case SettingsScreens.PrivacyPhoneP2P:
case SettingsScreens.PrivacyPhoneCall:
primaryPrivacy = privacy.phoneCall;

View File

@ -5,7 +5,7 @@ import React, {
import { getActions, getGlobal, withGlobal } from '../../../global';
import type { GlobalState } from '../../../global/types';
import type { ApiPrivacySettings, CustomPeerType } from '../../../types';
import type { ApiPrivacySettings, CustomPeerType, UniqueCustomPeer } from '../../../types';
import { SettingsScreens } from '../../../types';
import { ALL_FOLDER_ID, ARCHIVED_FOLDER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
@ -18,6 +18,7 @@ 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 PeerPicker from '../../common/pickers/PeerPicker';
@ -26,6 +27,7 @@ import FloatingActionButton from '../../ui/FloatingActionButton';
export type OwnProps = {
isAllowList?: boolean;
withPremiumCategory?: boolean;
withMiniAppsCategory?: boolean;
screen: SettingsScreens;
isActive?: boolean;
onScreenSelect: (screen: SettingsScreens) => void;
@ -42,6 +44,7 @@ const PREMIUM_CATEGORY = [CUSTOM_PEER_PREMIUM];
const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
isAllowList,
withPremiumCategory,
withMiniAppsCategory,
screen,
isActive,
currentUserId,
@ -51,7 +54,23 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
}) => {
const { setPrivacySettings } = getActions();
const lang = useOldLang();
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) {
@ -68,9 +87,10 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
if (!settings) {
return [];
}
return [settings.shouldAllowPremium ? CUSTOM_PEER_PREMIUM.type : undefined].filter(Boolean);
}, [settings]);
if (settings.shouldAllowPremium) { return [CUSTOM_PEER_PREMIUM.type]; }
if (settings.botsPrivacy === 'allow' && isAllowList) { return [customPeerBots.type]; }
return [];
}, [settings, isAllowList, customPeerBots]);
const [searchQuery, setSearchQuery] = useState<string>('');
const [isSubmitShown, setIsSubmitShown] = useState<boolean>(false);
const [newSelectedContactIds, setNewSelectedContactIds] = useState<string[]>(selectedContactIds);
@ -100,16 +120,16 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
return chatId !== currentUserId && chatId !== SERVICE_NOTIFICATIONS_USER_ID && !isChannel && !isDeleted;
});
const filteredChats = filterChatsByName(lang, chatIds, chatsById, searchQuery);
const filteredChats = filterChatsByName(oldLang, chatIds, chatsById, searchQuery);
// Show only relevant items
if (searchQuery) return filteredChats;
return unique([
...selectedContactIds,
...filterChatsByName(lang, chatIds, chatsById, searchQuery),
...filterChatsByName(oldLang, chatIds, chatsById, searchQuery),
]);
}, [folderAllOrderedIds, folderArchivedOrderedIds, selectedContactIds, lang, searchQuery, currentUserId]);
}, [folderAllOrderedIds, folderArchivedOrderedIds, selectedContactIds, oldLang, searchQuery, currentUserId]);
const handleSelectedCategoriesChange = useCallback((value: CustomPeerType[]) => {
setNewSelectedCategoryTypes(value);
@ -127,25 +147,41 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
isAllowList: Boolean(isAllowList),
updatedIds: newSelectedContactIds,
isPremiumAllowed: newSelectedCategoryTypes.includes(CUSTOM_PEER_PREMIUM.type) || undefined,
botsPrivacy: (!withMiniAppsCategory) ? 'none'
: (newSelectedCategoryTypes.includes(customPeerBots.type) ? 'allow' : 'disallow'),
});
onScreenSelect(SettingsScreens.Privacy);
}, [isAllowList, newSelectedCategoryTypes, newSelectedContactIds, onScreenSelect, screen]);
}, [
isAllowList,
withMiniAppsCategory,
newSelectedCategoryTypes,
newSelectedContactIds,
onScreenSelect,
screen,
customPeerBots,
]);
useHistoryBack({
isActive,
onBack: onReset,
});
function getCustomCategory() {
if (withPremiumCategory) return PREMIUM_CATEGORY;
if (withMiniAppsCategory && isAllowList) return miniAppsCategory;
return undefined;
}
return (
<div className="NewChat-inner step-1">
<PeerPicker
categories={withPremiumCategory ? PREMIUM_CATEGORY : undefined}
categories={getCustomCategory()}
itemIds={displayedIds || []}
selectedIds={newSelectedContactIds}
selectedCategories={newSelectedCategoryTypes}
filterValue={searchQuery}
filterPlaceholder={isAllowList ? lang('AlwaysAllowPlaceholder') : lang('NeverAllowPlaceholder')}
filterPlaceholder={isAllowList ? oldLang('AlwaysAllowPlaceholder') : oldLang('NeverAllowPlaceholder')}
categoryPlaceholderKey="PrivacyUserTypes"
searchInputId="new-group-picker-search"
isSearchable
@ -161,7 +197,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
<FloatingActionButton
isShown={isSubmitShown}
onClick={handleSubmit}
ariaLabel={isAllowList ? lang('AlwaysAllow') : lang('NeverAllow')}
ariaLabel={isAllowList ? oldLang('AlwaysAllow') : oldLang('NeverAllow')}
>
<i className="icon icon-check" />
</FloatingActionButton>
@ -187,6 +223,9 @@ function getCurrentPrivacySettings(global: GlobalState, screen: SettingsScreens)
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;

View File

@ -23,6 +23,10 @@ export function getPrivacyKey(screen: SettingsScreens): ApiPrivacyKey | undefine
case SettingsScreens.PrivacyBirthdayAllowedContacts:
case SettingsScreens.PrivacyBirthdayDeniedContacts:
return 'birthday';
case SettingsScreens.PrivacyGifts:
case SettingsScreens.PrivacyGiftsAllowedContacts:
case SettingsScreens.PrivacyGiftsDeniedContacts:
return 'gifts';
case SettingsScreens.PrivacyForwarding:
case SettingsScreens.PrivacyForwardingAllowedContacts:
case SettingsScreens.PrivacyForwardingDeniedContacts:

View File

@ -396,6 +396,7 @@ addActionHandler('loadPrivacySettings', async (global): Promise<void> => {
callApi('fetchPrivacySettings', 'voiceMessages'),
callApi('fetchPrivacySettings', 'bio'),
callApi('fetchPrivacySettings', 'birthday'),
callApi('fetchPrivacySettings', 'gifts'),
]);
if (result.some((e) => e === undefined)) {
@ -414,6 +415,7 @@ addActionHandler('loadPrivacySettings', async (global): Promise<void> => {
voiceMessagesSettings,
bioSettings,
birthdaySettings,
giftsSettings,
] = result as {
rules: ApiPrivacySettings;
}[];
@ -436,6 +438,7 @@ addActionHandler('loadPrivacySettings', async (global): Promise<void> => {
voiceMessages: voiceMessagesSettings.rules,
bio: bioSettings.rules,
birthday: birthdaySettings.rules,
gifts: giftsSettings.rules,
},
},
};
@ -477,6 +480,7 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload): Promi
visibility,
allowedIds: [...settings.allowUserIds, ...settings.allowChatIds],
blockedIds: [...settings.blockUserIds, ...settings.blockChatIds],
botsPrivacy: settings.botsPrivacy,
});
const result = await callApi('setPrivacySettings', privacyKey, rules);
@ -502,7 +506,7 @@ addActionHandler('setPrivacyVisibility', async (global, actions, payload): Promi
addActionHandler('setPrivacySettings', async (global, actions, payload): Promise<void> => {
const {
privacyKey, isAllowList, updatedIds, isPremiumAllowed,
privacyKey, isAllowList, updatedIds, isPremiumAllowed, botsPrivacy,
} = payload!;
const {
privacy: { [privacyKey]: settings },
@ -518,6 +522,7 @@ addActionHandler('setPrivacySettings', async (global, actions, payload): Promise
shouldAllowPremium: isPremiumAllowed,
allowedIds: isAllowList ? updatedIds : [...settings.allowUserIds, ...settings.allowChatIds],
blockedIds: !isAllowList ? updatedIds : [...settings.blockUserIds, ...settings.blockChatIds],
botsPrivacy,
});
const result = await callApi('setPrivacySettings', privacyKey, rules);

View File

@ -241,12 +241,13 @@ addActionHandler('toggleStoryPinnedToTop', async (global, actions, payload): Pro
const isRemoving = oldPinnedIds.includes(storyId);
const newPinnedIds = isRemoving ? oldPinnedIds.filter((id) => id !== storyId) : [...oldPinnedIds, storyId];
global = getGlobal();
global = {
...getGlobal(),
...global,
stories: {
...getGlobal().stories,
...global.stories,
byPeerId: {
...getGlobal().stories.byPeerId,
...global.stories.byPeerId,
[peerId]: {
...peerStories,
pinnedIds: newPinnedIds.sort((a, b) => b - a),
@ -520,6 +521,7 @@ addActionHandler('editStoryPrivacy', (global, actions, payload): ActionReturnTyp
isUnspecified: privacy.isUnspecified,
allowedIds,
blockedIds,
botsPrivacy: 'none',
});
void callApi('editStoryPrivacy', {

View File

@ -1,4 +1,4 @@
import type { ApiInputPrivacyRules, PrivacyVisibility } from '../../types';
import type { ApiInputPrivacyRules, BotsPrivacyType, PrivacyVisibility } from '../../types';
import type { GlobalState } from '../types';
import { partition } from '../../util/iteratees';
@ -10,12 +10,14 @@ export function buildApiInputPrivacyRules(global: GlobalState, {
allowedIds,
blockedIds,
shouldAllowPremium,
botsPrivacy,
}: {
visibility: PrivacyVisibility;
isUnspecified?: boolean;
allowedIds: string[];
blockedIds: string[];
shouldAllowPremium?: true;
botsPrivacy: BotsPrivacyType;
}): ApiInputPrivacyRules {
const {
users: { byId: usersById },
@ -33,6 +35,7 @@ export function buildApiInputPrivacyRules(global: GlobalState, {
blockedUsers: blockedUserIds.map((userId) => usersById[userId]).filter(Boolean),
blockedChats: blockedChatIds.map((chatId) => chatsById[chatId]).filter(Boolean),
shouldAllowPremium,
botsPrivacy,
};
return rules;

View File

@ -106,6 +106,7 @@ import type {
ApiPrivacyKey,
ApiPrivacySettings,
AudioOrigin,
BotsPrivacyType,
ChatCreationProgress,
ChatMediaSearchParams,
EmojiKeywords,
@ -1492,6 +1493,7 @@ export interface ActionPayloads {
isAllowList: boolean;
updatedIds: string[];
isPremiumAllowed?: true;
botsPrivacy: BotsPrivacyType;
};
loadNotificationExceptions: undefined;
setThemeSettings: { theme: ThemeKey } & Partial<IThemeSettings>;

View File

@ -134,6 +134,8 @@ export interface ISettings extends NotifySettings, Record<string, any> {
shouldSkipWebAppCloseConfirmation: boolean;
}
export type BotsPrivacyType = 'allow' | 'disallow' | 'none';
export interface ApiPrivacySettings {
visibility: PrivacyVisibility;
isUnspecified?: boolean;
@ -142,6 +144,7 @@ export interface ApiPrivacySettings {
blockUserIds: string[];
blockChatIds: string[];
shouldAllowPremium?: true;
botsPrivacy: BotsPrivacyType;
}
export interface ApiInputPrivacyRules {
@ -152,6 +155,7 @@ export interface ApiInputPrivacyRules {
blockedUsers?: ApiUser[];
blockedChats?: ApiChat[];
shouldAllowPremium?: true;
botsPrivacy: BotsPrivacyType;
}
export type IAnchorPosition = {
@ -183,6 +187,7 @@ export enum SettingsScreens {
PrivacyProfilePhoto,
PrivacyBio,
PrivacyBirthday,
PrivacyGifts,
PrivacyPhoneCall,
PrivacyPhoneP2P,
PrivacyForwarding,
@ -199,6 +204,8 @@ export enum SettingsScreens {
PrivacyBioDeniedContacts,
PrivacyBirthdayAllowedContacts,
PrivacyBirthdayDeniedContacts,
PrivacyGiftsAllowedContacts,
PrivacyGiftsDeniedContacts,
PrivacyPhoneCallAllowedContacts,
PrivacyPhoneCallDeniedContacts,
PrivacyPhoneP2PAllowedContacts,
@ -407,7 +414,7 @@ export type MiddleSearchResults = {
};
export type ApiPrivacyKey = 'phoneNumber' | 'addByPhone' | 'lastSeen' | 'profilePhoto' | 'voiceMessages' |
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P' | 'bio' | 'birthday';
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P' | 'bio' | 'birthday' | 'gifts';
export type PrivacyVisibility = 'everybody' | 'contacts' | 'closeFriends' | 'nonContacts' | 'nobody';
export interface LoadingState {

View File

@ -1159,6 +1159,11 @@ export interface LangPair {
'VideoConversionView': undefined;
'BotSuggestedStatusTitle': undefined;
'BotSuggestedStatusUpdated': undefined;
'PrivacyGifts': undefined;
'PrivacyGiftsTitle': undefined;
'PrivacyGiftsInfo': undefined;
'PrivacyValueBots': undefined;
'CustomShareGiftsInfo': undefined;
}
export interface LangPairWithVariables<V extends unknown = LangVariable> {