401 lines
13 KiB
TypeScript
401 lines
13 KiB
TypeScript
import type { FC } from '../../../lib/teact/teact';
|
|
import React, { memo, useCallback, useEffect } from '../../../lib/teact/teact';
|
|
import { getActions, withGlobal } from '../../../global';
|
|
|
|
import type { ApiPrivacySettings } from '../../../types';
|
|
import { SettingsScreens } from '../../../types';
|
|
|
|
import { selectCanSetPasscode, selectIsCurrentUserPremium } from '../../../global/selectors';
|
|
|
|
import useLang from '../../../hooks/useLang';
|
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
|
|
|
import ListItem from '../../ui/ListItem';
|
|
import Checkbox from '../../ui/Checkbox';
|
|
|
|
type OwnProps = {
|
|
isActive?: boolean;
|
|
onScreenSelect: (screen: SettingsScreens) => void;
|
|
onReset: () => void;
|
|
};
|
|
|
|
type StateProps = {
|
|
isCurrentUserPremium?: boolean;
|
|
hasPassword?: boolean;
|
|
hasPasscode?: boolean;
|
|
canSetPasscode?: boolean;
|
|
blockedCount: number;
|
|
webAuthCount: number;
|
|
isSensitiveEnabled?: boolean;
|
|
canChangeSensitive?: boolean;
|
|
canDisplayAutoarchiveSetting: boolean;
|
|
shouldArchiveAndMuteNewNonContact?: boolean;
|
|
canDisplayChatInTitle?: boolean;
|
|
privacyPhoneNumber?: ApiPrivacySettings;
|
|
privacyLastSeen?: ApiPrivacySettings;
|
|
privacyProfilePhoto?: ApiPrivacySettings;
|
|
privacyForwarding?: ApiPrivacySettings;
|
|
privacyVoiceMessages?: ApiPrivacySettings;
|
|
privacyGroupChats?: ApiPrivacySettings;
|
|
privacyPhoneCall?: ApiPrivacySettings;
|
|
privacyPhoneP2P?: ApiPrivacySettings;
|
|
};
|
|
|
|
const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|
isActive,
|
|
isCurrentUserPremium,
|
|
hasPassword,
|
|
hasPasscode,
|
|
blockedCount,
|
|
webAuthCount,
|
|
isSensitiveEnabled,
|
|
canChangeSensitive,
|
|
canDisplayAutoarchiveSetting,
|
|
shouldArchiveAndMuteNewNonContact,
|
|
canDisplayChatInTitle,
|
|
privacyPhoneNumber,
|
|
privacyLastSeen,
|
|
privacyProfilePhoto,
|
|
privacyForwarding,
|
|
privacyVoiceMessages,
|
|
privacyGroupChats,
|
|
privacyPhoneCall,
|
|
privacyPhoneP2P,
|
|
onScreenSelect,
|
|
onReset,
|
|
canSetPasscode,
|
|
}) => {
|
|
const {
|
|
loadPrivacySettings,
|
|
loadBlockedContacts,
|
|
loadAuthorizations,
|
|
loadContentSettings,
|
|
updateContentSettings,
|
|
loadGlobalPrivacySettings,
|
|
updateGlobalPrivacySettings,
|
|
loadWebAuthorizations,
|
|
showNotification,
|
|
setSettingOption,
|
|
} = getActions();
|
|
|
|
useEffect(() => {
|
|
loadBlockedContacts();
|
|
loadAuthorizations();
|
|
loadPrivacySettings();
|
|
loadContentSettings();
|
|
loadWebAuthorizations();
|
|
}, [loadBlockedContacts, loadAuthorizations, loadPrivacySettings, loadContentSettings, loadWebAuthorizations]);
|
|
|
|
useEffect(() => {
|
|
if (isActive) {
|
|
loadGlobalPrivacySettings();
|
|
}
|
|
}, [isActive, loadGlobalPrivacySettings]);
|
|
|
|
const lang = useLang();
|
|
|
|
useHistoryBack({
|
|
isActive,
|
|
onBack: onReset,
|
|
});
|
|
|
|
const handleArchiveAndMuteChange = useCallback((isEnabled: boolean) => {
|
|
updateGlobalPrivacySettings({
|
|
shouldArchiveAndMuteNewNonContact: isEnabled,
|
|
});
|
|
}, [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,
|
|
});
|
|
}, []);
|
|
|
|
const handleUpdateContentSettings = useCallback((isChecked: boolean) => {
|
|
updateContentSettings(isChecked);
|
|
}, [updateContentSettings]);
|
|
|
|
function getVisibilityValue(setting?: ApiPrivacySettings) {
|
|
const { visibility } = setting || {};
|
|
const blockCount = setting ? setting.blockChatIds.length + setting.blockUserIds.length : 0;
|
|
const allowCount = setting ? setting.allowChatIds.length + setting.allowUserIds.length : 0;
|
|
const total = [];
|
|
if (blockCount) total.push(`-${blockCount}`);
|
|
if (allowCount) total.push(`+${allowCount}`);
|
|
|
|
const exceptionString = total.length ? `(${total.join(',')})` : '';
|
|
|
|
switch (visibility) {
|
|
case 'everybody':
|
|
return `${lang('P2PEverybody')} ${exceptionString}`;
|
|
|
|
case 'contacts':
|
|
return `${lang('P2PContacts')} ${exceptionString}`;
|
|
|
|
case 'nobody':
|
|
return `${lang('P2PNobody')} ${exceptionString}`;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
return (
|
|
<div className="settings-content custom-scroll">
|
|
<div className="settings-item pt-3">
|
|
<ListItem
|
|
icon="delete-user"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyBlockedUsers)}
|
|
>
|
|
{lang('BlockedUsers')}
|
|
<span className="settings-item__current-value">{blockedCount || ''}</span>
|
|
</ListItem>
|
|
{canSetPasscode && (
|
|
<ListItem
|
|
icon="key"
|
|
narrow
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(
|
|
hasPasscode ? SettingsScreens.PasscodeEnabled : SettingsScreens.PasscodeDisabled,
|
|
)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('Passcode')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{lang(hasPasscode ? 'PasswordOn' : 'PasswordOff')}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
)}
|
|
<ListItem
|
|
icon="lock"
|
|
narrow
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(
|
|
hasPassword ? SettingsScreens.TwoFaEnabled : SettingsScreens.TwoFaDisabled,
|
|
)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('TwoStepVerification')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{lang(hasPassword ? 'PasswordOn' : 'PasswordOff')}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
{webAuthCount > 0 && (
|
|
<ListItem
|
|
icon="web"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.ActiveWebsites)}
|
|
>
|
|
{lang('PrivacySettings.WebSessions')}
|
|
<span className="settings-item__current-value">{webAuthCount}</span>
|
|
</ListItem>
|
|
)}
|
|
</div>
|
|
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header mb-4" dir={lang.isRtl ? 'rtl' : undefined}>{lang('PrivacyTitle')}</h4>
|
|
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneNumber)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('PrivacyPhoneTitle')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyPhoneNumber)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyLastSeen)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('LastSeenTitle')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyLastSeen)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyProfilePhoto)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('PrivacyProfilePhotoTitle')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyProfilePhoto)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneCall)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('WhoCanCallMe')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyPhoneCall)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyPhoneP2P)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('PrivacyP2P')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyPhoneP2P)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyForwarding)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('PrivacyForwardsTitle')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyForwarding)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
disabled={!isCurrentUserPremium}
|
|
allowDisabledClick
|
|
rightElement={!isCurrentUserPremium && <i className="icon icon-lock-badge settings-icon-locked" />}
|
|
className="no-icon"
|
|
onClick={handleVoiceMessagesClick}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('PrivacyVoiceMessagesTitle')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyVoiceMessages)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
<ListItem
|
|
narrow
|
|
className="no-icon"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => onScreenSelect(SettingsScreens.PrivacyGroupChats)}
|
|
>
|
|
<div className="multiline-menu-item">
|
|
<span className="title">{lang('WhoCanAddMe')}</span>
|
|
<span className="subtitle" dir="auto">
|
|
{getVisibilityValue(privacyGroupChats)}
|
|
</span>
|
|
</div>
|
|
</ListItem>
|
|
</div>
|
|
|
|
{canDisplayAutoarchiveSetting && (
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
|
{lang('NewChatsFromNonContacts')}
|
|
</h4>
|
|
<Checkbox
|
|
label={lang('ArchiveAndMute')}
|
|
subLabel={lang('ArchiveAndMuteInfo')}
|
|
checked={Boolean(shouldArchiveAndMuteNewNonContact)}
|
|
onCheck={handleArchiveAndMuteChange}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
|
{lang('lng_settings_window_system')}
|
|
</h4>
|
|
<Checkbox
|
|
label={lang('lng_settings_title_chat_name')}
|
|
checked={Boolean(canDisplayChatInTitle)}
|
|
onCheck={handleChatInTitleChange}
|
|
/>
|
|
</div>
|
|
|
|
{canChangeSensitive && (
|
|
<div className="settings-item">
|
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
|
{lang('lng_settings_sensitive_title')}
|
|
</h4>
|
|
<Checkbox
|
|
label={lang('lng_settings_sensitive_disable_filtering')}
|
|
subLabel={lang('lng_settings_sensitive_about')}
|
|
checked={Boolean(isSensitiveEnabled)}
|
|
disabled={!canChangeSensitive}
|
|
onCheck={handleUpdateContentSettings}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default memo(withGlobal<OwnProps>(
|
|
(global): StateProps => {
|
|
const {
|
|
settings: {
|
|
byKey: {
|
|
hasPassword, isSensitiveEnabled, canChangeSensitive, shouldArchiveAndMuteNewNonContact,
|
|
canDisplayChatInTitle,
|
|
},
|
|
privacy,
|
|
},
|
|
blocked,
|
|
passcode: {
|
|
hasPasscode,
|
|
},
|
|
appConfig,
|
|
} = global;
|
|
|
|
return {
|
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
|
hasPassword,
|
|
hasPasscode: Boolean(hasPasscode),
|
|
blockedCount: blocked.totalCount,
|
|
webAuthCount: global.activeWebSessions.orderedHashes.length,
|
|
isSensitiveEnabled,
|
|
canDisplayAutoarchiveSetting: Boolean(appConfig?.canDisplayAutoarchiveSetting),
|
|
shouldArchiveAndMuteNewNonContact,
|
|
canChangeSensitive,
|
|
privacyPhoneNumber: privacy.phoneNumber,
|
|
privacyLastSeen: privacy.lastSeen,
|
|
privacyProfilePhoto: privacy.profilePhoto,
|
|
privacyForwarding: privacy.forwards,
|
|
privacyVoiceMessages: privacy.voiceMessages,
|
|
privacyGroupChats: privacy.chatInvite,
|
|
privacyPhoneCall: privacy.phoneCall,
|
|
privacyPhoneP2P: privacy.phoneP2P,
|
|
canDisplayChatInTitle,
|
|
canSetPasscode: selectCanSetPasscode(global),
|
|
};
|
|
},
|
|
)(SettingsPrivacy));
|