Settings: Private message permissions (#4245)
This commit is contained in:
parent
3d4ba7c47b
commit
7569689fb2
@ -615,17 +615,24 @@ export async function fetchGlobalPrivacySettings() {
|
||||
return {
|
||||
shouldArchiveAndMuteNewNonContact: Boolean(result.archiveAndMuteNewNoncontactPeers),
|
||||
shouldHideReadMarks: Boolean(result.hideReadMarks),
|
||||
shouldNewNonContactPeersRequirePremium: Boolean(result.newNoncontactPeersRequirePremium),
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateGlobalPrivacySettings({ shouldArchiveAndMuteNewNonContact, shouldHideReadMarks }: {
|
||||
shouldArchiveAndMuteNewNonContact: boolean;
|
||||
shouldHideReadMarks: boolean;
|
||||
export async function updateGlobalPrivacySettings({
|
||||
shouldArchiveAndMuteNewNonContact,
|
||||
shouldHideReadMarks,
|
||||
shouldNewNonContactPeersRequirePremium,
|
||||
}: {
|
||||
shouldArchiveAndMuteNewNonContact?: boolean;
|
||||
shouldHideReadMarks?: boolean;
|
||||
shouldNewNonContactPeersRequirePremium?: boolean;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.account.SetGlobalPrivacySettings({
|
||||
settings: new GramJs.GlobalPrivacySettings({
|
||||
...(shouldArchiveAndMuteNewNonContact && { archiveAndMuteNewNoncontactPeers: true }),
|
||||
...(shouldHideReadMarks && { hideReadMarks: true }),
|
||||
...(shouldNewNonContactPeersRequirePremium && { newNoncontactPeersRequirePremium: true }),
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -636,6 +643,7 @@ export async function updateGlobalPrivacySettings({ shouldArchiveAndMuteNewNonCo
|
||||
return {
|
||||
shouldArchiveAndMuteNewNonContact: Boolean(result.archiveAndMuteNewNoncontactPeers),
|
||||
shouldHideReadMarks: Boolean(result.hideReadMarks),
|
||||
shouldNewNonContactPeersRequirePremium: Boolean(result.newNoncontactPeersRequirePremium),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -194,6 +194,7 @@ function LeftColumn({
|
||||
case SettingsScreens.PrivacyForwarding:
|
||||
case SettingsScreens.PrivacyGroupChats:
|
||||
case SettingsScreens.PrivacyVoiceMessages:
|
||||
case SettingsScreens.PrivacyMessages:
|
||||
case SettingsScreens.PrivacyBlockedUsers:
|
||||
case SettingsScreens.ActiveWebsites:
|
||||
case SettingsScreens.TwoFaDisabled:
|
||||
|
||||
33
src/components/left/settings/PremiumStatusItem.tsx
Normal file
33
src/components/left/settings/PremiumStatusItem.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React, { memo } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
|
||||
import PremiumIcon from '../../common/PremiumIcon';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
|
||||
function PremiumStatusItem() {
|
||||
const { openPremiumModal } = getActions();
|
||||
const lang = useLang();
|
||||
const handleOpenPremiumModal = useLastCallback(() => openPremiumModal());
|
||||
|
||||
return (
|
||||
<div className="settings-item">
|
||||
<ListItem
|
||||
leftElement={<PremiumIcon className="icon" withGradient big />}
|
||||
onClick={handleOpenPremiumModal}
|
||||
>
|
||||
{lang('PrivacyLastSeenPremium')}
|
||||
</ListItem>
|
||||
<p
|
||||
className="settings-item-description-larger premium-info"
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
>
|
||||
{lang('lng_messages_privacy_premium_about')}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(PremiumStatusItem);
|
||||
12
src/components/left/settings/PrivacyLockedOption.module.scss
Normal file
12
src/components/left/settings/PrivacyLockedOption.module.scss
Normal file
@ -0,0 +1,12 @@
|
||||
.contacts_and_premium_option-title {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lock-icon {
|
||||
font-size: 1.25rem;
|
||||
position: absolute;
|
||||
left: 1.0625rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--color-gray);
|
||||
}
|
||||
29
src/components/left/settings/PrivacyLockedOption.tsx
Normal file
29
src/components/left/settings/PrivacyLockedOption.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import React, { memo } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import Icon from '../../common/Icon';
|
||||
|
||||
import styles from './PrivacyLockedOption.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
function PrivacyLockedOption({ label }: OwnProps) {
|
||||
const lang = useLang();
|
||||
const { showNotification } = getActions();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.contactsAndPremiumOptionTitle}
|
||||
onClick={() => showNotification({ message: lang('OptionPremiumRequiredMessage') })}
|
||||
>
|
||||
<span>{label}</span>
|
||||
<Icon name="lock-badge" className={styles.lockIcon} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(PrivacyLockedOption);
|
||||
80
src/components/left/settings/PrivacyMessages.tsx
Normal file
80
src/components/left/settings/PrivacyMessages.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import React, { memo, useMemo } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import { selectIsCurrentUserPremium, selectNewNoncontactPeersRequirePremium } from '../../../global/selectors';
|
||||
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
|
||||
import RadioGroup from '../../ui/RadioGroup';
|
||||
import PremiumStatusItem from './PremiumStatusItem';
|
||||
import PrivacyLockedOption from './PrivacyLockedOption';
|
||||
|
||||
type OwnProps = {
|
||||
isActive?: boolean;
|
||||
onReset: VoidFunction;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
shouldNewNonContactPeersRequirePremium?: boolean;
|
||||
isCurrentUserPremium?: boolean;
|
||||
};
|
||||
|
||||
function PrivacyMessages({
|
||||
isActive, onReset, shouldNewNonContactPeersRequirePremium, isCurrentUserPremium,
|
||||
}: OwnProps & StateProps) {
|
||||
const { updateGlobalPrivacySettings } = getActions();
|
||||
const lang = useLang();
|
||||
|
||||
const options = useMemo(() => {
|
||||
return [
|
||||
{ value: 'everybody', label: lang('P2PEverybody') },
|
||||
{
|
||||
value: 'contacts_and_premium',
|
||||
label: isCurrentUserPremium ? (
|
||||
lang('PrivacyMessagesContactsAndPremium')
|
||||
) : (
|
||||
<PrivacyLockedOption label={lang('PrivacyMessagesContactsAndPremium')} />
|
||||
),
|
||||
hidden: !isCurrentUserPremium,
|
||||
},
|
||||
];
|
||||
}, [lang, isCurrentUserPremium]);
|
||||
|
||||
const handleChange = useLastCallback((privacy: string) => {
|
||||
updateGlobalPrivacySettings({ shouldNewNonContactPeersRequirePremium: privacy === 'contacts_and_premium' });
|
||||
});
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
onBack: onReset,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="settings-item">
|
||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('PrivacyMessagesTitle')}
|
||||
</h4>
|
||||
<RadioGroup
|
||||
name="privacy-messages"
|
||||
options={options}
|
||||
onChange={handleChange}
|
||||
selected={shouldNewNonContactPeersRequirePremium ? 'contacts_and_premium' : 'everybody'}
|
||||
/>
|
||||
<p className="settings-item-description-larger" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('Privacy.Messages.SectionFooter')}
|
||||
</p>
|
||||
</div>
|
||||
{!isCurrentUserPremium && <PremiumStatusItem />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(withGlobal<OwnProps>((global): StateProps => {
|
||||
return {
|
||||
shouldNewNonContactPeersRequirePremium: selectNewNoncontactPeersRequirePremium(global),
|
||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||
};
|
||||
})(PrivacyMessages));
|
||||
@ -180,6 +180,10 @@
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
|
||||
&.premium-info {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
&[dir="rtl"] {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import Transition from '../../ui/Transition';
|
||||
import SettingsFolders from './folders/SettingsFolders';
|
||||
import SettingsPasscode from './passcode/SettingsPasscode';
|
||||
import PrivacyMessages from './PrivacyMessages';
|
||||
import SettingsActiveSessions from './SettingsActiveSessions';
|
||||
import SettingsActiveWebsites from './SettingsActiveWebsites';
|
||||
import SettingsCustomEmoji from './SettingsCustomEmoji';
|
||||
@ -372,6 +373,14 @@ const Settings: FC<OwnProps> = ({
|
||||
/>
|
||||
);
|
||||
|
||||
case SettingsScreens.PrivacyMessages:
|
||||
return (
|
||||
<PrivacyMessages
|
||||
isActive={isScreenActive}
|
||||
onReset={handleReset}
|
||||
/>
|
||||
);
|
||||
|
||||
case SettingsScreens.Folders:
|
||||
case SettingsScreens.FoldersCreateFolder:
|
||||
case SettingsScreens.FoldersEditFolder:
|
||||
|
||||
@ -119,6 +119,8 @@ const SettingsHeader: FC<OwnProps> = ({
|
||||
return <h3>{lang('PrivacyForwards')}</h3>;
|
||||
case SettingsScreens.PrivacyVoiceMessages:
|
||||
return <h3>{lang('PrivacyVoiceMessages')}</h3>;
|
||||
case SettingsScreens.PrivacyMessages:
|
||||
return <h3>{lang('PrivacyMessages')}</h3>;
|
||||
case SettingsScreens.PrivacyGroupChats:
|
||||
return <h3>{lang('AutodownloadGroupChats')}</h3>;
|
||||
case SettingsScreens.PrivacyPhoneCall:
|
||||
|
||||
@ -10,6 +10,7 @@ import { selectCanSetPasscode, selectIsCurrentUserPremium } from '../../../globa
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import PremiumIcon from '../../common/PremiumIcon';
|
||||
import Checkbox from '../../ui/Checkbox';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
|
||||
@ -30,6 +31,7 @@ type StateProps = {
|
||||
canChangeSensitive?: boolean;
|
||||
canDisplayAutoarchiveSetting: boolean;
|
||||
shouldArchiveAndMuteNewNonContact?: boolean;
|
||||
shouldNewNonContactPeersRequirePremium?: boolean;
|
||||
canDisplayChatInTitle?: boolean;
|
||||
privacyPhoneNumber?: ApiPrivacySettings;
|
||||
privacyLastSeen?: ApiPrivacySettings;
|
||||
@ -52,6 +54,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||
canChangeSensitive,
|
||||
canDisplayAutoarchiveSetting,
|
||||
shouldArchiveAndMuteNewNonContact,
|
||||
shouldNewNonContactPeersRequirePremium,
|
||||
canDisplayChatInTitle,
|
||||
canSetPasscode,
|
||||
privacyPhoneNumber,
|
||||
@ -73,7 +76,6 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||
loadGlobalPrivacySettings,
|
||||
updateGlobalPrivacySettings,
|
||||
loadWebAuthorizations,
|
||||
showNotification,
|
||||
setSettingOption,
|
||||
} = getActions();
|
||||
|
||||
@ -103,16 +105,6 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
}, [updateGlobalPrivacySettings]);
|
||||
|
||||
const handleVoiceMessagesClick = useCallback(() => {
|
||||
if (isCurrentUserPremium) {
|
||||
onScreenSelect(SettingsScreens.PrivacyVoiceMessages);
|
||||
} else {
|
||||
showNotification({
|
||||
message: lang('PrivacyVoiceMessagesPremiumOnly'),
|
||||
});
|
||||
}
|
||||
}, [isCurrentUserPremium, lang, onScreenSelect, showNotification]);
|
||||
|
||||
const handleChatInTitleChange = useCallback((isChecked: boolean) => {
|
||||
setSettingOption({
|
||||
canDisplayChatInTitle: isChecked,
|
||||
@ -298,11 +290,11 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||
</ListItem>
|
||||
<ListItem
|
||||
narrow
|
||||
disabled={!isCurrentUserPremium}
|
||||
allowDisabledClick
|
||||
rightElement={!isCurrentUserPremium && <i className="icon icon-lock-badge settings-icon-locked" />}
|
||||
rightElement={isCurrentUserPremium && <PremiumIcon big withGradient />}
|
||||
className="no-icon"
|
||||
onClick={handleVoiceMessagesClick}
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => onScreenSelect(SettingsScreens.PrivacyVoiceMessages)}
|
||||
>
|
||||
<div className="multiline-menu-item">
|
||||
<span className="title">{lang('PrivacyVoiceMessagesTitle')}</span>
|
||||
@ -311,6 +303,22 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
narrow
|
||||
rightElement={isCurrentUserPremium && <PremiumIcon big withGradient />}
|
||||
className="no-icon"
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => onScreenSelect(SettingsScreens.PrivacyMessages)}
|
||||
>
|
||||
<div className="multiline-menu-item">
|
||||
<span className="title">{lang('PrivacyMessagesTitle')}</span>
|
||||
<span className="subtitle" dir="auto">
|
||||
{shouldNewNonContactPeersRequirePremium
|
||||
? lang('PrivacyMessagesContactsAndPremium')
|
||||
: lang('P2PEverybody')}
|
||||
</span>
|
||||
</div>
|
||||
</ListItem>
|
||||
</div>
|
||||
|
||||
{canDisplayAutoarchiveSetting && (
|
||||
@ -362,7 +370,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
settings: {
|
||||
byKey: {
|
||||
hasPassword, isSensitiveEnabled, canChangeSensitive, shouldArchiveAndMuteNewNonContact,
|
||||
canDisplayChatInTitle,
|
||||
canDisplayChatInTitle, shouldNewNonContactPeersRequirePremium,
|
||||
},
|
||||
privacy,
|
||||
},
|
||||
@ -383,6 +391,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
canDisplayAutoarchiveSetting: Boolean(appConfig?.canDisplayAutoarchiveSetting),
|
||||
shouldArchiveAndMuteNewNonContact,
|
||||
canChangeSensitive,
|
||||
shouldNewNonContactPeersRequirePremium,
|
||||
privacyPhoneNumber: privacy.phoneNumber,
|
||||
privacyLastSeen: privacy.lastSeen,
|
||||
privacyProfilePhoto: privacy.profilePhoto,
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
:global(.settings-item-description-larger).premiumInfo {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
@ -4,7 +4,6 @@ import { getActions, withGlobal } from '../../../global';
|
||||
import type { PrivacyVisibility } from '../../../types';
|
||||
|
||||
import { selectIsCurrentUserPremium, selectShouldHideReadMarks } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
@ -14,8 +13,6 @@ import PremiumIcon from '../../common/PremiumIcon';
|
||||
import Checkbox from '../../ui/Checkbox';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
|
||||
import styles from './SettingsPrivacyLastSeen.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
visibility?: PrivacyVisibility;
|
||||
};
|
||||
@ -59,10 +56,7 @@ const SettingsPrivacyLastSeen = ({
|
||||
{isCurrentUserPremium ? lang('PrivacyLastSeenPremiumForPremium') : lang('PrivacyLastSeenPremium')}
|
||||
</ListItem>
|
||||
<p
|
||||
className={buildClassName(
|
||||
'settings-item-description-larger',
|
||||
styles.premiumInfo,
|
||||
)}
|
||||
className="settings-item-description-larger premium-info"
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
>
|
||||
{isCurrentUserPremium
|
||||
|
||||
@ -6,7 +6,7 @@ import type { ApiPhoto } from '../../../api/types';
|
||||
import type { ApiPrivacySettings } from '../../../types';
|
||||
import { SettingsScreens } from '../../../types';
|
||||
|
||||
import { selectUserFullInfo } from '../../../global/selectors';
|
||||
import { selectIsCurrentUserPremium, selectUserFullInfo } from '../../../global/selectors';
|
||||
import { getPrivacyKey } from './helpers/privacy';
|
||||
|
||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||
@ -15,6 +15,8 @@ import useLastCallback from '../../../hooks/useLastCallback';
|
||||
|
||||
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';
|
||||
|
||||
@ -31,6 +33,7 @@ type StateProps = {
|
||||
currentUserFallbackPhoto?: ApiPhoto;
|
||||
primaryPrivacy?: ApiPrivacySettings;
|
||||
secondaryPrivacy?: ApiPrivacySettings;
|
||||
isPremiumRequired?: boolean;
|
||||
};
|
||||
|
||||
const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
||||
@ -41,6 +44,7 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
||||
currentUserId,
|
||||
hasCurrentUserFullInfo,
|
||||
currentUserFallbackPhoto,
|
||||
isPremiumRequired,
|
||||
onScreenSelect,
|
||||
onReset,
|
||||
}) => {
|
||||
@ -67,6 +71,7 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
||||
screen={screen}
|
||||
privacy={primaryPrivacy}
|
||||
onScreenSelect={onScreenSelect}
|
||||
isPremiumRequired={isPremiumRequired}
|
||||
/>
|
||||
{screen === SettingsScreens.PrivacyProfilePhoto && primaryPrivacy?.visibility !== 'everybody' && (
|
||||
<SettingsPrivacyPublicProfilePhoto
|
||||
@ -93,9 +98,11 @@ function PrivacySubsection({
|
||||
screen,
|
||||
privacy,
|
||||
onScreenSelect,
|
||||
isPremiumRequired,
|
||||
}: {
|
||||
screen: SettingsScreens;
|
||||
privacy?: ApiPrivacySettings;
|
||||
isPremiumRequired?: boolean;
|
||||
onScreenSelect: (screen: SettingsScreens) => void;
|
||||
}) {
|
||||
const { setPrivacyVisibility } = getActions();
|
||||
@ -105,13 +112,30 @@ function PrivacySubsection({
|
||||
const hasNobody = screen !== SettingsScreens.PrivacyAddByPhone;
|
||||
const options = [
|
||||
{ value: 'everybody', label: lang('P2PEverybody') },
|
||||
{ value: 'contacts', label: lang('P2PContacts') },
|
||||
{
|
||||
value: 'contacts',
|
||||
label: isPremiumRequired ? (
|
||||
<PrivacyLockedOption label={lang('P2PContacts')} />
|
||||
) : (
|
||||
lang('P2PContacts')
|
||||
),
|
||||
hidden: isPremiumRequired,
|
||||
},
|
||||
];
|
||||
|
||||
if (hasNobody) {
|
||||
options.push({ value: 'nobody', label: lang('P2PNobody') });
|
||||
options.push({
|
||||
value: 'nobody',
|
||||
label: isPremiumRequired ? (
|
||||
<PrivacyLockedOption label={lang('P2PNobody')} />
|
||||
) : (
|
||||
lang('P2PNobody')
|
||||
),
|
||||
hidden: isPremiumRequired,
|
||||
});
|
||||
}
|
||||
return options;
|
||||
}, [lang, screen]);
|
||||
}, [lang, screen, isPremiumRequired]);
|
||||
|
||||
const primaryExceptionLists = useMemo(() => {
|
||||
if (screen === SettingsScreens.PrivacyAddByPhone) {
|
||||
@ -136,6 +160,8 @@ function PrivacySubsection({
|
||||
case SettingsScreens.PrivacyAddByPhone: {
|
||||
return privacy?.visibility === 'everybody' ? lang('PrivacyPhoneInfo') : lang('PrivacyPhoneInfo3');
|
||||
}
|
||||
case SettingsScreens.PrivacyVoiceMessages:
|
||||
return lang('PrivacyVoiceMessagesInfo');
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
@ -257,7 +283,7 @@ function PrivacySubsection({
|
||||
<p className="settings-item-description-larger" dir={lang.isRtl ? 'rtl' : undefined}>{descriptionText}</p>
|
||||
)}
|
||||
</div>
|
||||
{(primaryExceptionLists.shouldShowAllowed || primaryExceptionLists.shouldShowDenied) && (
|
||||
{!isPremiumRequired && (primaryExceptionLists.shouldShowAllowed || primaryExceptionLists.shouldShowDenied) && (
|
||||
<div className="settings-item">
|
||||
<h4 className="settings-item-header mb-4" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('PrivacyExceptions')}
|
||||
@ -294,6 +320,7 @@ function PrivacySubsection({
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isPremiumRequired && <PremiumStatusItem />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -361,6 +388,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
currentUserId: currentUserId!,
|
||||
hasCurrentUserFullInfo: Boolean(currentUserFullInfo),
|
||||
currentUserFallbackPhoto: currentUserFullInfo?.fallbackPhoto,
|
||||
isPremiumRequired: screen === SettingsScreens.PrivacyVoiceMessages && !selectIsCurrentUserPremium(global),
|
||||
};
|
||||
},
|
||||
)(SettingsPrivacyVisibility));
|
||||
|
||||
@ -20,6 +20,7 @@ type OwnProps = {
|
||||
disabled?: boolean;
|
||||
hidden?: boolean;
|
||||
isLoading?: boolean;
|
||||
className?: string;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
};
|
||||
|
||||
@ -33,18 +34,20 @@ const Radio: FC<OwnProps> = ({
|
||||
disabled,
|
||||
hidden,
|
||||
isLoading,
|
||||
className,
|
||||
onChange,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
const className = buildClassName(
|
||||
const fullClassName = buildClassName(
|
||||
'Radio',
|
||||
className,
|
||||
disabled && 'disabled',
|
||||
hidden && 'hidden-widget',
|
||||
isLoading && 'loading',
|
||||
);
|
||||
|
||||
return (
|
||||
<label className={className} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<label className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<input
|
||||
type="radio"
|
||||
name={name}
|
||||
|
||||
@ -9,6 +9,7 @@ export type IRadioOption = {
|
||||
subLabel?: string;
|
||||
value: string;
|
||||
hidden?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
type OwnProps = {
|
||||
@ -47,6 +48,7 @@ const RadioGroup: FC<OwnProps> = ({
|
||||
hidden={option.hidden}
|
||||
disabled={disabled}
|
||||
isLoading={loadingOption ? loadingOption === option.value : undefined}
|
||||
className={option.className}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -674,6 +674,8 @@ addActionHandler('updateGlobalPrivacySettings', async (global, actions, payload)
|
||||
const shouldArchiveAndMuteNewNonContact = payload.shouldArchiveAndMuteNewNonContact
|
||||
?? Boolean(global.settings.byKey.shouldArchiveAndMuteNewNonContact);
|
||||
const shouldHideReadMarks = payload.shouldHideReadMarks ?? Boolean(global.settings.byKey.shouldHideReadMarks);
|
||||
const shouldNewNonContactPeersRequirePremium = payload.shouldNewNonContactPeersRequirePremium
|
||||
?? Boolean(global.settings.byKey.shouldNewNonContactPeersRequirePremium);
|
||||
|
||||
global = replaceSettings(global, { shouldArchiveAndMuteNewNonContact, shouldHideReadMarks });
|
||||
setGlobal(global);
|
||||
@ -681,6 +683,7 @@ addActionHandler('updateGlobalPrivacySettings', async (global, actions, payload)
|
||||
const result = await callApi('updateGlobalPrivacySettings', {
|
||||
shouldArchiveAndMuteNewNonContact,
|
||||
shouldHideReadMarks,
|
||||
shouldNewNonContactPeersRequirePremium,
|
||||
});
|
||||
|
||||
global = getGlobal();
|
||||
@ -689,6 +692,9 @@ addActionHandler('updateGlobalPrivacySettings', async (global, actions, payload)
|
||||
? !shouldArchiveAndMuteNewNonContact
|
||||
: result.shouldArchiveAndMuteNewNonContact,
|
||||
shouldHideReadMarks: !result ? !shouldHideReadMarks : result.shouldHideReadMarks,
|
||||
shouldNewNonContactPeersRequirePremium: !result
|
||||
? !shouldNewNonContactPeersRequirePremium
|
||||
: result.shouldNewNonContactPeersRequirePremium,
|
||||
});
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
@ -242,6 +242,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
||||
wasTimeFormatSetManually: false,
|
||||
isConnectionStatusMinimized: true,
|
||||
shouldArchiveAndMuteNewNonContact: false,
|
||||
shouldNewNonContactPeersRequirePremium: false,
|
||||
shouldHideReadMarks: false,
|
||||
canTranslate: false,
|
||||
canTranslateChats: true,
|
||||
|
||||
@ -20,6 +20,10 @@ export function selectTranslationLanguage<T extends GlobalState>(global: T) {
|
||||
return global.settings.byKey.translationLanguage || selectLanguageCode(global);
|
||||
}
|
||||
|
||||
export function selectNewNoncontactPeersRequirePremium<T extends GlobalState>(global: T) {
|
||||
return global.settings.byKey.shouldNewNonContactPeersRequirePremium;
|
||||
}
|
||||
|
||||
export function selectShouldHideReadMarks<T extends GlobalState>(global: T) {
|
||||
return global.settings.byKey.shouldHideReadMarks;
|
||||
}
|
||||
|
||||
@ -2873,7 +2873,11 @@ export interface ActionPayloads {
|
||||
} & WithTabId;
|
||||
closeShareChatFolderModal: undefined | WithTabId;
|
||||
loadGlobalPrivacySettings: undefined;
|
||||
updateGlobalPrivacySettings: { shouldArchiveAndMuteNewNonContact?: boolean; shouldHideReadMarks?: boolean };
|
||||
updateGlobalPrivacySettings: {
|
||||
shouldArchiveAndMuteNewNonContact?: boolean;
|
||||
shouldHideReadMarks?: boolean;
|
||||
shouldNewNonContactPeersRequirePremium?: boolean;
|
||||
};
|
||||
|
||||
// Premium
|
||||
openPremiumModal: ({
|
||||
|
||||
@ -101,6 +101,7 @@ export interface ISettings extends NotifySettings, Record<string, any> {
|
||||
wasTimeFormatSetManually: boolean;
|
||||
isConnectionStatusMinimized: boolean;
|
||||
shouldArchiveAndMuteNewNonContact?: boolean;
|
||||
shouldNewNonContactPeersRequirePremium?: boolean;
|
||||
shouldHideReadMarks?: boolean;
|
||||
canTranslate: boolean;
|
||||
canTranslateChats: boolean;
|
||||
@ -183,6 +184,7 @@ export enum SettingsScreens {
|
||||
PrivacyPhoneP2P,
|
||||
PrivacyForwarding,
|
||||
PrivacyVoiceMessages,
|
||||
PrivacyMessages,
|
||||
PrivacyGroupChats,
|
||||
PrivacyPhoneNumberAllowedContacts,
|
||||
PrivacyPhoneNumberDeniedContacts,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user