Settings / Privacy: Voice Messages (#1968)
This commit is contained in:
parent
1eb030b2d8
commit
21a989b165
@ -71,6 +71,8 @@ export function buildPrivacyKey(key: GramJs.TypePrivacyKey): ApiPrivacyKey | und
|
|||||||
return 'phoneP2P';
|
return 'phoneP2P';
|
||||||
case 'PrivacyKeyForwards':
|
case 'PrivacyKeyForwards':
|
||||||
return 'forwards';
|
return 'forwards';
|
||||||
|
case 'PrivacyKeyVoiceMessages':
|
||||||
|
return 'voiceMessages';
|
||||||
case 'PrivacyKeyChatInvite':
|
case 'PrivacyKeyChatInvite':
|
||||||
return 'chatInvite';
|
return 'chatInvite';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -452,6 +452,9 @@ export function buildInputPrivacyKey(privacyKey: ApiPrivacyKey) {
|
|||||||
|
|
||||||
case 'phoneP2P':
|
case 'phoneP2P':
|
||||||
return new GramJs.InputPrivacyKeyPhoneP2P();
|
return new GramJs.InputPrivacyKeyPhoneP2P();
|
||||||
|
|
||||||
|
case 'voiceMessages':
|
||||||
|
return new GramJs.InputPrivacyKeyVoiceMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@ -36,13 +36,13 @@ export async function fetchFullUser({
|
|||||||
}) {
|
}) {
|
||||||
const input = buildInputEntity(id, accessHash);
|
const input = buildInputEntity(id, accessHash);
|
||||||
if (!(input instanceof GramJs.InputUser)) {
|
if (!(input instanceof GramJs.InputUser)) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullInfo = await invokeRequest(new GramJs.users.GetFullUser({ id: input }));
|
const fullInfo = await invokeRequest(new GramJs.users.GetFullUser({ id: input }));
|
||||||
|
|
||||||
if (!fullInfo) {
|
if (!fullInfo) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullInfo.fullUser.profilePhoto instanceof GramJs.Photo) {
|
if (fullInfo.fullUser.profilePhoto instanceof GramJs.Photo) {
|
||||||
@ -66,6 +66,8 @@ export async function fetchFullUser({
|
|||||||
fullInfo: userWithFullInfo.fullInfo,
|
fullInfo: userWithFullInfo.fullInfo,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return userWithFullInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchCommonChats(id: string, accessHash?: string, maxId?: string) {
|
export async function fetchCommonChats(id: string, accessHash?: string, maxId?: string) {
|
||||||
|
|||||||
@ -149,14 +149,18 @@ const DeleteChatModal: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
function renderMessage() {
|
function renderMessage() {
|
||||||
if (isChannel && chat.isCreator) {
|
if (isChannel && chat.isCreator) {
|
||||||
return <p>{renderText(lang('ChatList.DeleteAndLeaveGroupConfirmation', chatTitle), ['simple_markdown'])}</p>;
|
return (
|
||||||
|
<p>
|
||||||
|
{renderText(lang('ChatList.DeleteAndLeaveGroupConfirmation', chatTitle), ['simple_markdown', 'emoji'])}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isChannel && !chat.isCreator) || isBasicGroup || isSuperGroup) {
|
if ((isChannel && !chat.isCreator) || isBasicGroup || isSuperGroup) {
|
||||||
return <p>{renderText(lang('ChannelLeaveAlertWithName', chatTitle), ['simple_markdown'])}</p>;
|
return <p>{renderText(lang('ChannelLeaveAlertWithName', chatTitle), ['simple_markdown', 'emoji'])}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <p>{renderText(lang('ChatList.DeleteChatConfirmation', contactName), ['simple_markdown'])}</p>;
|
return <p>{renderText(lang('ChatList.DeleteChatConfirmation', contactName), ['simple_markdown', 'emoji'])}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderActionText() {
|
function renderActionText() {
|
||||||
|
|||||||
@ -164,6 +164,7 @@ const LeftColumn: FC<StateProps> = ({
|
|||||||
case SettingsScreens.PrivacyPhoneP2P:
|
case SettingsScreens.PrivacyPhoneP2P:
|
||||||
case SettingsScreens.PrivacyForwarding:
|
case SettingsScreens.PrivacyForwarding:
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
case SettingsScreens.PrivacyBlockedUsers:
|
case SettingsScreens.PrivacyBlockedUsers:
|
||||||
case SettingsScreens.ActiveWebsites:
|
case SettingsScreens.ActiveWebsites:
|
||||||
case SettingsScreens.TwoFaDisabled:
|
case SettingsScreens.TwoFaDisabled:
|
||||||
@ -220,6 +221,10 @@ const LeftColumn: FC<StateProps> = ({
|
|||||||
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
||||||
setSettingsScreen(SettingsScreens.PrivacyForwarding);
|
setSettingsScreen(SettingsScreens.PrivacyForwarding);
|
||||||
return;
|
return;
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
|
||||||
|
setSettingsScreen(SettingsScreens.PrivacyVoiceMessages);
|
||||||
|
return;
|
||||||
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
||||||
setSettingsScreen(SettingsScreens.PrivacyGroupChats);
|
setSettingsScreen(SettingsScreens.PrivacyGroupChats);
|
||||||
|
|||||||
@ -58,6 +58,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-icon-locked {
|
||||||
|
align-self: center;
|
||||||
|
margin-right: 0.25rem !important;
|
||||||
|
font-size: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
#monkey {
|
#monkey {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
@ -183,6 +189,7 @@
|
|||||||
|
|
||||||
.multiline-menu-item {
|
.multiline-menu-item {
|
||||||
white-space: initial;
|
white-space: initial;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
&.full-size {
|
&.full-size {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -104,6 +104,11 @@ const PRIVACY_FORWARDING_SCREENS = [
|
|||||||
SettingsScreens.PrivacyForwardingDeniedContacts,
|
SettingsScreens.PrivacyForwardingDeniedContacts,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const PRIVACY_VOICE_MESSAGES_SCREENS = [
|
||||||
|
SettingsScreens.PrivacyVoiceMessagesAllowedContacts,
|
||||||
|
SettingsScreens.PrivacyVoiceMessagesDeniedContacts,
|
||||||
|
];
|
||||||
|
|
||||||
const PRIVACY_GROUP_CHATS_SCREENS = [
|
const PRIVACY_GROUP_CHATS_SCREENS = [
|
||||||
SettingsScreens.PrivacyGroupChatsAllowedContacts,
|
SettingsScreens.PrivacyGroupChatsAllowedContacts,
|
||||||
SettingsScreens.PrivacyGroupChatsDeniedContacts,
|
SettingsScreens.PrivacyGroupChatsDeniedContacts,
|
||||||
@ -178,6 +183,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
[SettingsScreens.PrivacyPhoneCall]: PRIVACY_PHONE_CALL_SCREENS.includes(screen),
|
[SettingsScreens.PrivacyPhoneCall]: PRIVACY_PHONE_CALL_SCREENS.includes(screen),
|
||||||
[SettingsScreens.PrivacyPhoneP2P]: PRIVACY_PHONE_P2P_SCREENS.includes(screen),
|
[SettingsScreens.PrivacyPhoneP2P]: PRIVACY_PHONE_P2P_SCREENS.includes(screen),
|
||||||
[SettingsScreens.PrivacyForwarding]: PRIVACY_FORWARDING_SCREENS.includes(screen),
|
[SettingsScreens.PrivacyForwarding]: PRIVACY_FORWARDING_SCREENS.includes(screen),
|
||||||
|
[SettingsScreens.PrivacyVoiceMessages]: PRIVACY_VOICE_MESSAGES_SCREENS.includes(screen),
|
||||||
[SettingsScreens.PrivacyGroupChats]: PRIVACY_GROUP_CHATS_SCREENS.includes(screen),
|
[SettingsScreens.PrivacyGroupChats]: PRIVACY_GROUP_CHATS_SCREENS.includes(screen),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -284,6 +290,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
case SettingsScreens.PrivacyPhoneCall:
|
case SettingsScreens.PrivacyPhoneCall:
|
||||||
case SettingsScreens.PrivacyPhoneP2P:
|
case SettingsScreens.PrivacyPhoneP2P:
|
||||||
case SettingsScreens.PrivacyForwarding:
|
case SettingsScreens.PrivacyForwarding:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
return (
|
return (
|
||||||
<SettingsPrivacyVisibility
|
<SettingsPrivacyVisibility
|
||||||
@ -300,6 +307,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
case SettingsScreens.PrivacyPhoneCallAllowedContacts:
|
case SettingsScreens.PrivacyPhoneCallAllowedContacts:
|
||||||
case SettingsScreens.PrivacyPhoneP2PAllowedContacts:
|
case SettingsScreens.PrivacyPhoneP2PAllowedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
||||||
return (
|
return (
|
||||||
<SettingsPrivacyVisibilityExceptionList
|
<SettingsPrivacyVisibilityExceptionList
|
||||||
@ -317,6 +325,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
case SettingsScreens.PrivacyPhoneCallDeniedContacts:
|
case SettingsScreens.PrivacyPhoneCallDeniedContacts:
|
||||||
case SettingsScreens.PrivacyPhoneP2PDeniedContacts:
|
case SettingsScreens.PrivacyPhoneP2PDeniedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
||||||
return (
|
return (
|
||||||
<SettingsPrivacyVisibilityExceptionList
|
<SettingsPrivacyVisibilityExceptionList
|
||||||
|
|||||||
@ -110,18 +110,22 @@ const SettingsHeader: FC<OwnProps> = ({
|
|||||||
return <h3>{lang('Privacy.ProfilePhoto')}</h3>;
|
return <h3>{lang('Privacy.ProfilePhoto')}</h3>;
|
||||||
case SettingsScreens.PrivacyForwarding:
|
case SettingsScreens.PrivacyForwarding:
|
||||||
return <h3>{lang('PrivacyForwards')}</h3>;
|
return <h3>{lang('PrivacyForwards')}</h3>;
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
return <h3>{lang('PrivacyVoiceMessages')}</h3>;
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
return <h3>{lang('AutodownloadGroupChats')}</h3>;
|
return <h3>{lang('AutodownloadGroupChats')}</h3>;
|
||||||
case SettingsScreens.PrivacyPhoneNumberAllowedContacts:
|
case SettingsScreens.PrivacyPhoneNumberAllowedContacts:
|
||||||
case SettingsScreens.PrivacyLastSeenAllowedContacts:
|
case SettingsScreens.PrivacyLastSeenAllowedContacts:
|
||||||
case SettingsScreens.PrivacyProfilePhotoAllowedContacts:
|
case SettingsScreens.PrivacyProfilePhotoAllowedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
||||||
return <h3>{lang('AlwaysShareWith')}</h3>;
|
return <h3>{lang('AlwaysShareWith')}</h3>;
|
||||||
case SettingsScreens.PrivacyPhoneNumberDeniedContacts:
|
case SettingsScreens.PrivacyPhoneNumberDeniedContacts:
|
||||||
case SettingsScreens.PrivacyLastSeenDeniedContacts:
|
case SettingsScreens.PrivacyLastSeenDeniedContacts:
|
||||||
case SettingsScreens.PrivacyProfilePhotoDeniedContacts:
|
case SettingsScreens.PrivacyProfilePhotoDeniedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
||||||
return <h3>{lang('NeverShareWith')}</h3>;
|
return <h3>{lang('NeverShareWith')}</h3>;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { getActions, withGlobal } from '../../../global';
|
|||||||
import type { ApiPrivacySettings } from '../../../types';
|
import type { ApiPrivacySettings } from '../../../types';
|
||||||
import { SettingsScreens } from '../../../types';
|
import { SettingsScreens } from '../../../types';
|
||||||
|
|
||||||
|
import { selectIsCurrentUserPremium } from '../../../global/selectors';
|
||||||
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ type OwnProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
|
isCurrentUserPremium?: boolean;
|
||||||
hasPassword?: boolean;
|
hasPassword?: boolean;
|
||||||
hasPasscode?: boolean;
|
hasPasscode?: boolean;
|
||||||
blockedCount: number;
|
blockedCount: number;
|
||||||
@ -29,6 +32,7 @@ type StateProps = {
|
|||||||
privacyLastSeen?: ApiPrivacySettings;
|
privacyLastSeen?: ApiPrivacySettings;
|
||||||
privacyProfilePhoto?: ApiPrivacySettings;
|
privacyProfilePhoto?: ApiPrivacySettings;
|
||||||
privacyForwarding?: ApiPrivacySettings;
|
privacyForwarding?: ApiPrivacySettings;
|
||||||
|
privacyVoiceMessages?: ApiPrivacySettings;
|
||||||
privacyGroupChats?: ApiPrivacySettings;
|
privacyGroupChats?: ApiPrivacySettings;
|
||||||
privacyPhoneCall?: ApiPrivacySettings;
|
privacyPhoneCall?: ApiPrivacySettings;
|
||||||
privacyPhoneP2P?: ApiPrivacySettings;
|
privacyPhoneP2P?: ApiPrivacySettings;
|
||||||
@ -36,6 +40,7 @@ type StateProps = {
|
|||||||
|
|
||||||
const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
||||||
isActive,
|
isActive,
|
||||||
|
isCurrentUserPremium,
|
||||||
hasPassword,
|
hasPassword,
|
||||||
hasPasscode,
|
hasPasscode,
|
||||||
blockedCount,
|
blockedCount,
|
||||||
@ -47,6 +52,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
privacyLastSeen,
|
privacyLastSeen,
|
||||||
privacyProfilePhoto,
|
privacyProfilePhoto,
|
||||||
privacyForwarding,
|
privacyForwarding,
|
||||||
|
privacyVoiceMessages,
|
||||||
privacyGroupChats,
|
privacyGroupChats,
|
||||||
privacyPhoneCall,
|
privacyPhoneCall,
|
||||||
privacyPhoneP2P,
|
privacyPhoneP2P,
|
||||||
@ -62,6 +68,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
loadGlobalPrivacySettings,
|
loadGlobalPrivacySettings,
|
||||||
updateGlobalPrivacySettings,
|
updateGlobalPrivacySettings,
|
||||||
loadWebAuthorizations,
|
loadWebAuthorizations,
|
||||||
|
showNotification,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -91,6 +98,16 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
});
|
});
|
||||||
}, [updateGlobalPrivacySettings]);
|
}, [updateGlobalPrivacySettings]);
|
||||||
|
|
||||||
|
const handleVoiceMessagesClick = useCallback(() => {
|
||||||
|
if (isCurrentUserPremium) {
|
||||||
|
onScreenSelect(SettingsScreens.PrivacyVoiceMessages);
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
message: lang('PrivacyVoiceMessagesPremiumOnly'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [isCurrentUserPremium, lang, onScreenSelect, showNotification]);
|
||||||
|
|
||||||
function getVisibilityValue(setting?: ApiPrivacySettings) {
|
function getVisibilityValue(setting?: ApiPrivacySettings) {
|
||||||
const { visibility } = setting || {};
|
const { visibility } = setting || {};
|
||||||
const blockCount = setting ? setting.blockChatIds.length + setting.blockUserIds.length : 0;
|
const blockCount = setting ? setting.blockChatIds.length + setting.blockUserIds.length : 0;
|
||||||
@ -256,6 +273,21 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
narrow
|
||||||
|
disabled={!isCurrentUserPremium}
|
||||||
|
allowDisabledClick
|
||||||
|
rightElement={!isCurrentUserPremium && <i className="icon-lock-badge settings-icon-locked" />}
|
||||||
|
className="no-icon"
|
||||||
|
onClick={handleVoiceMessagesClick}
|
||||||
|
>
|
||||||
|
<div className="multiline-menu-item">
|
||||||
|
<span className="title">{lang('PrivacyVoiceMessages')}</span>
|
||||||
|
<span className="subtitle" dir="auto">
|
||||||
|
{getVisibilityValue(privacyVoiceMessages)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
narrow
|
narrow
|
||||||
className="no-icon"
|
className="no-icon"
|
||||||
@ -317,6 +349,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
} = global;
|
} = global;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
hasPassword,
|
hasPassword,
|
||||||
hasPasscode: Boolean(hasPasscode),
|
hasPasscode: Boolean(hasPasscode),
|
||||||
blockedCount: blocked.totalCount,
|
blockedCount: blocked.totalCount,
|
||||||
@ -328,6 +361,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
privacyLastSeen: privacy.lastSeen,
|
privacyLastSeen: privacy.lastSeen,
|
||||||
privacyProfilePhoto: privacy.profilePhoto,
|
privacyProfilePhoto: privacy.profilePhoto,
|
||||||
privacyForwarding: privacy.forwards,
|
privacyForwarding: privacy.forwards,
|
||||||
|
privacyVoiceMessages: privacy.voiceMessages,
|
||||||
privacyGroupChats: privacy.chatInvite,
|
privacyGroupChats: privacy.chatInvite,
|
||||||
privacyPhoneCall: privacy.phoneCall,
|
privacyPhoneCall: privacy.phoneCall,
|
||||||
privacyPhoneP2P: privacy.phoneP2P,
|
privacyPhoneP2P: privacy.phoneP2P,
|
||||||
|
|||||||
@ -77,6 +77,8 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
|||||||
return lang('PrivacyProfilePhotoTitle');
|
return lang('PrivacyProfilePhotoTitle');
|
||||||
case SettingsScreens.PrivacyForwarding:
|
case SettingsScreens.PrivacyForwarding:
|
||||||
return lang('PrivacyForwardsTitle');
|
return lang('PrivacyForwardsTitle');
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
return lang('PrivacyVoiceMessagesTitle');
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
return lang('WhoCanAddMe');
|
return lang('WhoCanAddMe');
|
||||||
case SettingsScreens.PrivacyPhoneCall:
|
case SettingsScreens.PrivacyPhoneCall:
|
||||||
@ -116,6 +118,8 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
|||||||
return SettingsScreens.PrivacyPhoneCallAllowedContacts;
|
return SettingsScreens.PrivacyPhoneCallAllowedContacts;
|
||||||
case SettingsScreens.PrivacyPhoneP2P:
|
case SettingsScreens.PrivacyPhoneP2P:
|
||||||
return SettingsScreens.PrivacyPhoneP2PAllowedContacts;
|
return SettingsScreens.PrivacyPhoneP2PAllowedContacts;
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
return SettingsScreens.PrivacyVoiceMessagesAllowedContacts;
|
||||||
default:
|
default:
|
||||||
return SettingsScreens.PrivacyGroupChatsAllowedContacts;
|
return SettingsScreens.PrivacyGroupChatsAllowedContacts;
|
||||||
}
|
}
|
||||||
@ -135,6 +139,8 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
|
|||||||
return SettingsScreens.PrivacyPhoneCallDeniedContacts;
|
return SettingsScreens.PrivacyPhoneCallDeniedContacts;
|
||||||
case SettingsScreens.PrivacyPhoneP2P:
|
case SettingsScreens.PrivacyPhoneP2P:
|
||||||
return SettingsScreens.PrivacyPhoneP2PDeniedContacts;
|
return SettingsScreens.PrivacyPhoneP2PDeniedContacts;
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
return SettingsScreens.PrivacyVoiceMessagesDeniedContacts;
|
||||||
default:
|
default:
|
||||||
return SettingsScreens.PrivacyGroupChatsDeniedContacts;
|
return SettingsScreens.PrivacyGroupChatsDeniedContacts;
|
||||||
}
|
}
|
||||||
@ -258,6 +264,10 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
privacySettings = privacy.forwards;
|
privacySettings = privacy.forwards;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
privacySettings = privacy.voiceMessages;
|
||||||
|
break;
|
||||||
|
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
privacySettings = privacy.chatInvite;
|
privacySettings = privacy.chatInvite;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -143,6 +143,9 @@ function getCurrentPrivacySettings(global: GlobalState, screen: SettingsScreens)
|
|||||||
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
||||||
return privacy.forwards;
|
return privacy.forwards;
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
|
||||||
|
return privacy.voiceMessages;
|
||||||
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
||||||
return privacy.chatInvite;
|
return privacy.chatInvite;
|
||||||
|
|||||||
@ -19,6 +19,10 @@ export function getPrivacyKey(screen: SettingsScreens): ApiPrivacyKey | undefine
|
|||||||
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
case SettingsScreens.PrivacyForwardingAllowedContacts:
|
||||||
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
case SettingsScreens.PrivacyForwardingDeniedContacts:
|
||||||
return 'forwards';
|
return 'forwards';
|
||||||
|
case SettingsScreens.PrivacyVoiceMessages:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesAllowedContacts:
|
||||||
|
case SettingsScreens.PrivacyVoiceMessagesDeniedContacts:
|
||||||
|
return 'voiceMessages';
|
||||||
case SettingsScreens.PrivacyGroupChats:
|
case SettingsScreens.PrivacyGroupChats:
|
||||||
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
case SettingsScreens.PrivacyGroupChatsAllowedContacts:
|
||||||
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
case SettingsScreens.PrivacyGroupChatsDeniedContacts:
|
||||||
|
|||||||
@ -40,7 +40,7 @@ const BotTrustModal: FC<OwnProps> = ({ bot, type }) => {
|
|||||||
onClose={cancelBotTrustRequest}
|
onClose={cancelBotTrustRequest}
|
||||||
confirmHandler={handleBotTrustAccept}
|
confirmHandler={handleBotTrustAccept}
|
||||||
title={title}
|
title={title}
|
||||||
textParts={renderText(text, ['br', 'simple_markdown'])}
|
textParts={renderText(text, ['br', 'simple_markdown', 'emoji'])}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -153,7 +153,8 @@ const Dialogs: FC<StateProps> = ({ dialogs }) => {
|
|||||||
className="error"
|
className="error"
|
||||||
title={getErrorHeader(error)}
|
title={getErrorHeader(error)}
|
||||||
>
|
>
|
||||||
{error.hasErrorKey ? getReadableErrorText(error) : renderText(error.message!, ['emoji', 'br'])}
|
{error.hasErrorKey ? getReadableErrorText(error)
|
||||||
|
: renderText(error.message!, ['simple_markdown', 'emoji', 'br'])}
|
||||||
<div>
|
<div>
|
||||||
<Button isText onClick={closeModal}>{lang('OK')}</Button>
|
<Button isText onClick={closeModal}>{lang('OK')}</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,11 +26,11 @@ const Notifications: FC<StateProps> = ({ notifications }) => {
|
|||||||
message, className, localId, action, actionText, title,
|
message, className, localId, action, actionText, title,
|
||||||
}) => (
|
}) => (
|
||||||
<Notification
|
<Notification
|
||||||
title={title ? renderText(title, ['emoji', 'br', 'links', 'simple_markdown']) : undefined}
|
title={title ? renderText(title, ['simple_markdown', 'emoji', 'br', 'links']) : undefined}
|
||||||
action={action}
|
action={action}
|
||||||
actionText={actionText}
|
actionText={actionText}
|
||||||
className={className}
|
className={className}
|
||||||
message={renderText(message, ['emoji', 'br', 'links', 'simple_markdown'])}
|
message={renderText(message, ['simple_markdown', 'emoji', 'br', 'links'])}
|
||||||
// eslint-disable-next-line react/jsx-no-bind
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
onDismiss={() => dismissNotification({ localId })}
|
onDismiss={() => dismissNotification({ localId })}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -85,7 +85,6 @@ type StateProps = {
|
|||||||
audioMessage?: ApiMessage;
|
audioMessage?: ApiMessage;
|
||||||
messagesCount?: number;
|
messagesCount?: number;
|
||||||
isChatWithSelf?: boolean;
|
isChatWithSelf?: boolean;
|
||||||
isChatWithBot?: boolean;
|
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
hasButtonInHeader?: boolean;
|
hasButtonInHeader?: boolean;
|
||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
@ -111,7 +110,6 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
chat,
|
chat,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
isChatWithSelf,
|
isChatWithSelf,
|
||||||
isChatWithBot,
|
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
hasButtonInHeader,
|
hasButtonInHeader,
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
@ -338,7 +336,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
typingStatus={typingStatus}
|
typingStatus={typingStatus}
|
||||||
status={connectionStatusText}
|
status={connectionStatusText}
|
||||||
withDots={Boolean(connectionStatusText)}
|
withDots={Boolean(connectionStatusText)}
|
||||||
withFullInfo={isChatWithBot}
|
withFullInfo
|
||||||
withMediaViewer
|
withMediaViewer
|
||||||
withUpdatingStatus
|
withUpdatingStatus
|
||||||
withVideoAvatar
|
withVideoAvatar
|
||||||
@ -483,7 +481,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
chat,
|
chat,
|
||||||
messagesCount,
|
messagesCount,
|
||||||
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
isChatWithSelf: selectIsChatWithSelf(global, chatId),
|
||||||
isChatWithBot,
|
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
||||||
|
|||||||
@ -175,6 +175,7 @@ type StateProps =
|
|||||||
fileSizeLimit: number;
|
fileSizeLimit: number;
|
||||||
captionLimit: number;
|
captionLimit: number;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
|
canSendVoiceByPrivacy?: boolean;
|
||||||
}
|
}
|
||||||
& Pick<GlobalState, 'connectionState'>;
|
& Pick<GlobalState, 'connectionState'>;
|
||||||
|
|
||||||
@ -214,6 +215,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
chat,
|
chat,
|
||||||
isForCurrentMessageList,
|
isForCurrentMessageList,
|
||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
|
canSendVoiceByPrivacy,
|
||||||
connectionState,
|
connectionState,
|
||||||
isChatWithBot,
|
isChatWithBot,
|
||||||
isChatWithSelf,
|
isChatWithSelf,
|
||||||
@ -269,6 +271,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
resetOpenChatWithText,
|
resetOpenChatWithText,
|
||||||
callAttachMenuBot,
|
callAttachMenuBot,
|
||||||
openLimitReachedModal,
|
openLimitReachedModal,
|
||||||
|
showNotification,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
@ -903,14 +906,26 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
}, [isSelectModeActive, enableHover, disableHover, isReady]);
|
}, [isSelectModeActive, enableHover, disableHover, isReady]);
|
||||||
|
|
||||||
|
const areVoiceMessagesNotAllowed = mainButtonState === MainButtonState.Record
|
||||||
|
&& (!canAttachMedia || !canSendVoiceByPrivacy);
|
||||||
|
|
||||||
const mainButtonHandler = useCallback(() => {
|
const mainButtonHandler = useCallback(() => {
|
||||||
switch (mainButtonState) {
|
switch (mainButtonState) {
|
||||||
case MainButtonState.Send:
|
case MainButtonState.Send:
|
||||||
handleSend();
|
handleSend();
|
||||||
break;
|
break;
|
||||||
case MainButtonState.Record:
|
case MainButtonState.Record: {
|
||||||
void startRecordingVoice();
|
if (areVoiceMessagesNotAllowed) {
|
||||||
|
if (!canSendVoiceByPrivacy) {
|
||||||
|
showNotification({
|
||||||
|
message: lang('VoiceMessagesRestrictedByPrivacy', chat?.title),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startRecordingVoice();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case MainButtonState.Edit:
|
case MainButtonState.Edit:
|
||||||
handleEditComplete();
|
handleEditComplete();
|
||||||
break;
|
break;
|
||||||
@ -926,12 +941,11 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
mainButtonState, handleSend, startRecordingVoice, handleEditComplete, activeVoiceRecording, requestCalendar,
|
mainButtonState, handleSend, handleEditComplete, activeVoiceRecording, requestCalendar, areVoiceMessagesNotAllowed,
|
||||||
pauseRecordingVoice, handleMessageSchedule,
|
canSendVoiceByPrivacy, showNotification, lang, chat?.title, startRecordingVoice, pauseRecordingVoice,
|
||||||
|
handleMessageSchedule,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const areVoiceMessagesNotAllowed = mainButtonState === MainButtonState.Record && !canAttachMedia;
|
|
||||||
|
|
||||||
const prevEditedMessage = usePrevious(editingMessage, true);
|
const prevEditedMessage = usePrevious(editingMessage, true);
|
||||||
const renderedEditedMessage = editingMessage || prevEditedMessage;
|
const renderedEditedMessage = editingMessage || prevEditedMessage;
|
||||||
|
|
||||||
@ -948,7 +962,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
sendButtonAriaLabel = 'Save edited message';
|
sendButtonAriaLabel = 'Save edited message';
|
||||||
break;
|
break;
|
||||||
case MainButtonState.Record:
|
case MainButtonState.Record:
|
||||||
sendButtonAriaLabel = areVoiceMessagesNotAllowed
|
sendButtonAriaLabel = !canAttachMedia
|
||||||
? 'Conversation.DefaultRestrictedMedia'
|
? 'Conversation.DefaultRestrictedMedia'
|
||||||
: 'AccDescrVoiceMessage';
|
: 'AccDescrVoiceMessage';
|
||||||
}
|
}
|
||||||
@ -1254,6 +1268,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
|||||||
color="secondary"
|
color="secondary"
|
||||||
className={buildClassName(mainButtonState, !isReady && 'not-ready', activeVoiceRecording && 'recording')}
|
className={buildClassName(mainButtonState, !isReady && 'not-ready', activeVoiceRecording && 'recording')}
|
||||||
disabled={areVoiceMessagesNotAllowed}
|
disabled={areVoiceMessagesNotAllowed}
|
||||||
|
allowDisabledClick
|
||||||
ariaLabel={lang(sendButtonAriaLabel)}
|
ariaLabel={lang(sendButtonAriaLabel)}
|
||||||
onClick={mainButtonHandler}
|
onClick={mainButtonHandler}
|
||||||
onContextMenu={
|
onContextMenu={
|
||||||
@ -1305,6 +1320,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const isForCurrentMessageList = chatId === currentMessageList?.chatId
|
const isForCurrentMessageList = chatId === currentMessageList?.chatId
|
||||||
&& threadId === currentMessageList?.threadId
|
&& threadId === currentMessageList?.threadId
|
||||||
&& messageListType === currentMessageList?.type;
|
&& messageListType === currentMessageList?.type;
|
||||||
|
const user = selectUser(global, chatId);
|
||||||
|
const canSendVoiceByPrivacy = (user && !user.fullInfo?.noVoiceMessages) ?? true;
|
||||||
|
|
||||||
const editingDraft = messageListType === 'scheduled'
|
const editingDraft = messageListType === 'scheduled'
|
||||||
? selectEditingScheduledDraft(global, chatId)
|
? selectEditingScheduledDraft(global, chatId)
|
||||||
@ -1358,6 +1375,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
fileSizeLimit: selectCurrentLimit(global, 'uploadMaxFileparts') * MAX_UPLOAD_FILEPART_SIZE,
|
fileSizeLimit: selectCurrentLimit(global, 'uploadMaxFileparts') * MAX_UPLOAD_FILEPART_SIZE,
|
||||||
captionLimit: selectCurrentLimit(global, 'captionLength'),
|
captionLimit: selectCurrentLimit(global, 'captionLength'),
|
||||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
|
canSendVoiceByPrivacy,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(Composer));
|
)(Composer));
|
||||||
|
|||||||
@ -55,7 +55,9 @@
|
|||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: 0.5 !important;
|
opacity: 0.5 !important;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
pointer-events: none;
|
&:not(.click-allowed) {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.round {
|
&.round {
|
||||||
|
|||||||
@ -33,6 +33,7 @@ export type OwnProps = {
|
|||||||
href?: string;
|
href?: string;
|
||||||
download?: string;
|
download?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
allowDisabledClick?: boolean;
|
||||||
ripple?: boolean;
|
ripple?: boolean;
|
||||||
faded?: boolean;
|
faded?: boolean;
|
||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
@ -79,6 +80,7 @@ const Button: FC<OwnProps> = ({
|
|||||||
href,
|
href,
|
||||||
download,
|
download,
|
||||||
disabled,
|
disabled,
|
||||||
|
allowDisabledClick,
|
||||||
ripple,
|
ripple,
|
||||||
faded,
|
faded,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
@ -104,6 +106,7 @@ const Button: FC<OwnProps> = ({
|
|||||||
pill && 'pill',
|
pill && 'pill',
|
||||||
fluid && 'fluid',
|
fluid && 'fluid',
|
||||||
disabled && 'disabled',
|
disabled && 'disabled',
|
||||||
|
allowDisabledClick && 'click-allowed',
|
||||||
isText && 'text',
|
isText && 'text',
|
||||||
isLoading && 'loading',
|
isLoading && 'loading',
|
||||||
ripple && 'has-ripple',
|
ripple && 'has-ripple',
|
||||||
@ -114,7 +117,7 @@ const Button: FC<OwnProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleClick = useCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const handleClick = useCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
if (!disabled && onClick) {
|
if ((allowDisabledClick || !disabled) && onClick) {
|
||||||
onClick(e);
|
onClick(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,15 +127,15 @@ const Button: FC<OwnProps> = ({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsClicked(false);
|
setIsClicked(false);
|
||||||
}, CLICKED_TIMEOUT);
|
}, CLICKED_TIMEOUT);
|
||||||
}, [disabled, onClick, shouldStopPropagation]);
|
}, [allowDisabledClick, disabled, onClick, shouldStopPropagation]);
|
||||||
|
|
||||||
const handleMouseDown = useCallback((e: ReactMouseEvent<HTMLButtonElement>) => {
|
const handleMouseDown = useCallback((e: ReactMouseEvent<HTMLButtonElement>) => {
|
||||||
if (!noPreventDefault) e.preventDefault();
|
if (!noPreventDefault) e.preventDefault();
|
||||||
|
|
||||||
if (!disabled && onMouseDown) {
|
if ((allowDisabledClick || !disabled) && onMouseDown) {
|
||||||
onMouseDown(e);
|
onMouseDown(e);
|
||||||
}
|
}
|
||||||
}, [disabled, noPreventDefault, onMouseDown]);
|
}, [allowDisabledClick, disabled, noPreventDefault, onMouseDown]);
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -69,12 +69,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled:not(.click-allowed) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.ListItem-button {
|
&.disabled .ListItem-button {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.disabled):not(.is-static) {
|
&:not(.disabled):not(.is-static) {
|
||||||
@ -86,6 +86,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
--background-color: var(--color-chat-hover);
|
--background-color: var(--color-chat-hover);
|
||||||
@ -202,7 +203,8 @@
|
|||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PremiumIcon, .VerifiedIcon {
|
.PremiumIcon,
|
||||||
|
.VerifiedIcon {
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,11 +30,13 @@ interface OwnProps {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
leftElement?: TeactNode;
|
leftElement?: TeactNode;
|
||||||
secondaryIcon?: string;
|
secondaryIcon?: string;
|
||||||
|
rightElement?: TeactNode;
|
||||||
buttonClassName?: string;
|
buttonClassName?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: string;
|
style?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
allowDisabledClick?: boolean;
|
||||||
ripple?: boolean;
|
ripple?: boolean;
|
||||||
narrow?: boolean;
|
narrow?: boolean;
|
||||||
inactive?: boolean;
|
inactive?: boolean;
|
||||||
@ -56,10 +58,12 @@ const ListItem: FC<OwnProps> = ({
|
|||||||
leftElement,
|
leftElement,
|
||||||
buttonClassName,
|
buttonClassName,
|
||||||
secondaryIcon,
|
secondaryIcon,
|
||||||
|
rightElement,
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
children,
|
children,
|
||||||
disabled,
|
disabled,
|
||||||
|
allowDisabledClick,
|
||||||
ripple,
|
ripple,
|
||||||
narrow,
|
narrow,
|
||||||
inactive,
|
inactive,
|
||||||
@ -108,7 +112,7 @@ const ListItem: FC<OwnProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
||||||
if (disabled || !onClick) {
|
if ((disabled && !allowDisabledClick) || !onClick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onClick(e);
|
onClick(e);
|
||||||
@ -117,10 +121,10 @@ const ListItem: FC<OwnProps> = ({
|
|||||||
markIsTouched();
|
markIsTouched();
|
||||||
fastRaf(unmarkIsTouched);
|
fastRaf(unmarkIsTouched);
|
||||||
}
|
}
|
||||||
}, [disabled, markIsTouched, onClick, ripple, unmarkIsTouched]);
|
}, [allowDisabledClick, disabled, markIsTouched, onClick, ripple, unmarkIsTouched]);
|
||||||
|
|
||||||
const handleSecondaryIconClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const handleSecondaryIconClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
if (disabled || e.button !== 0 || (!onSecondaryIconClick && !contextActions)) return;
|
if ((disabled && !allowDisabledClick) || e.button !== 0 || (!onSecondaryIconClick && !contextActions)) return;
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (onSecondaryIconClick) {
|
if (onSecondaryIconClick) {
|
||||||
onSecondaryIconClick(e);
|
onSecondaryIconClick(e);
|
||||||
@ -154,6 +158,7 @@ const ListItem: FC<OwnProps> = ({
|
|||||||
ripple && 'has-ripple',
|
ripple && 'has-ripple',
|
||||||
narrow && 'narrow',
|
narrow && 'narrow',
|
||||||
disabled && 'disabled',
|
disabled && 'disabled',
|
||||||
|
allowDisabledClick && 'click-allowed',
|
||||||
inactive && 'inactive',
|
inactive && 'inactive',
|
||||||
contextMenuPosition && 'has-menu-open',
|
contextMenuPosition && 'has-menu-open',
|
||||||
focus && 'focus',
|
focus && 'focus',
|
||||||
@ -201,6 +206,7 @@ const ListItem: FC<OwnProps> = ({
|
|||||||
<i className={`icon-${secondaryIcon}`} />
|
<i className={`icon-${secondaryIcon}`} />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{rightElement}
|
||||||
</div>
|
</div>
|
||||||
{contextActions && contextMenuPosition !== undefined && (
|
{contextActions && contextMenuPosition !== undefined && (
|
||||||
<Menu
|
<Menu
|
||||||
|
|||||||
@ -40,7 +40,6 @@ const Notification: FC<OwnProps> = ({
|
|||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const timerRef = useRef<number | undefined>(null);
|
const timerRef = useRef<number | undefined>(null);
|
||||||
|
|
||||||
const { transitionClassNames } = useShowTransition(isOpen);
|
const { transitionClassNames } = useShowTransition(isOpen);
|
||||||
|
|
||||||
const closeAndDismiss = useCallback(() => {
|
const closeAndDismiss = useCallback(() => {
|
||||||
|
|||||||
@ -69,9 +69,12 @@ import {
|
|||||||
selectUser,
|
selectUser,
|
||||||
selectSendAs,
|
selectSendAs,
|
||||||
selectSponsoredMessage,
|
selectSponsoredMessage,
|
||||||
|
selectForwardsContainVoiceMessages,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { debounce, onTickEnd, rafPromise } from '../../../util/schedulers';
|
import {
|
||||||
import { getMessageOriginalId, isServiceNotificationMessage } from '../../helpers';
|
debounce, onTickEnd, rafPromise,
|
||||||
|
} from '../../../util/schedulers';
|
||||||
|
import { getMessageOriginalId, getUserFullName, isServiceNotificationMessage } from '../../helpers';
|
||||||
import { getTranslation } from '../../../util/langProvider';
|
import { getTranslation } from '../../../util/langProvider';
|
||||||
import { ensureProtocol } from '../../../util/ensureProtocol';
|
import { ensureProtocol } from '../../../util/ensureProtocol';
|
||||||
|
|
||||||
@ -1245,6 +1248,39 @@ addActionHandler('openUrl', (global, actions, payload) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('setForwardChatId', async (global, actions, payload) => {
|
||||||
|
const { id } = payload;
|
||||||
|
let user = selectUser(global, id);
|
||||||
|
if (user && selectForwardsContainVoiceMessages(global)) {
|
||||||
|
if (!user.fullInfo) {
|
||||||
|
const { accessHash } = user;
|
||||||
|
user = await callApi('fetchFullUser', { id, accessHash });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user?.fullInfo!.noVoiceMessages) {
|
||||||
|
actions.showDialog({
|
||||||
|
data: {
|
||||||
|
message: getTranslation('VoiceMessagesRestrictedByPrivacy', getUserFullName(user)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setGlobal({
|
||||||
|
...global,
|
||||||
|
forwardMessages: {
|
||||||
|
...global.forwardMessages,
|
||||||
|
toChatId: id,
|
||||||
|
isModalShown: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
actions.openChat({ id });
|
||||||
|
actions.closeMediaViewer();
|
||||||
|
actions.exitMessageSelectMode();
|
||||||
|
});
|
||||||
|
|
||||||
function countSortedIds(ids: number[], from: number, to: number) {
|
function countSortedIds(ids: number[], from: number, to: number) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
|||||||
@ -318,6 +318,7 @@ addActionHandler('loadPrivacySettings', async (global) => {
|
|||||||
chatInviteSettings,
|
chatInviteSettings,
|
||||||
phoneCallSettings,
|
phoneCallSettings,
|
||||||
phoneP2PSettings,
|
phoneP2PSettings,
|
||||||
|
voiceMessagesSettings,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
callApi('fetchPrivacySettings', 'phoneNumber'),
|
callApi('fetchPrivacySettings', 'phoneNumber'),
|
||||||
callApi('fetchPrivacySettings', 'lastSeen'),
|
callApi('fetchPrivacySettings', 'lastSeen'),
|
||||||
@ -326,6 +327,7 @@ addActionHandler('loadPrivacySettings', async (global) => {
|
|||||||
callApi('fetchPrivacySettings', 'chatInvite'),
|
callApi('fetchPrivacySettings', 'chatInvite'),
|
||||||
callApi('fetchPrivacySettings', 'phoneCall'),
|
callApi('fetchPrivacySettings', 'phoneCall'),
|
||||||
callApi('fetchPrivacySettings', 'phoneP2P'),
|
callApi('fetchPrivacySettings', 'phoneP2P'),
|
||||||
|
callApi('fetchPrivacySettings', 'voiceMessages'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -336,6 +338,7 @@ addActionHandler('loadPrivacySettings', async (global) => {
|
|||||||
|| !chatInviteSettings
|
|| !chatInviteSettings
|
||||||
|| !phoneCallSettings
|
|| !phoneCallSettings
|
||||||
|| !phoneP2PSettings
|
|| !phoneP2PSettings
|
||||||
|
|| !voiceMessagesSettings
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -354,6 +357,7 @@ addActionHandler('loadPrivacySettings', async (global) => {
|
|||||||
chatInvite: chatInviteSettings,
|
chatInvite: chatInviteSettings,
|
||||||
phoneCall: phoneCallSettings,
|
phoneCall: phoneCallSettings,
|
||||||
phoneP2P: phoneP2PSettings,
|
phoneP2P: phoneP2PSettings,
|
||||||
|
voiceMessages: voiceMessagesSettings,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -471,23 +471,6 @@ addActionHandler('exitForwardMode', (global) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('setForwardChatId', (global, actions, payload) => {
|
|
||||||
const { id } = payload;
|
|
||||||
|
|
||||||
setGlobal({
|
|
||||||
...global,
|
|
||||||
forwardMessages: {
|
|
||||||
...global.forwardMessages,
|
|
||||||
toChatId: id,
|
|
||||||
isModalShown: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
actions.openChat({ id });
|
|
||||||
actions.closeMediaViewer();
|
|
||||||
actions.exitMessageSelectMode();
|
|
||||||
});
|
|
||||||
|
|
||||||
addActionHandler('openForwardMenuForSelectedMessages', (global, actions) => {
|
addActionHandler('openForwardMenuForSelectedMessages', (global, actions) => {
|
||||||
if (!global.selectedMessages) {
|
if (!global.selectedMessages) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -975,3 +975,13 @@ export function selectCanScheduleUntilOnline(global: GlobalState, id: string) {
|
|||||||
!isChatWithSelf && !chatBot && isUserId(id) && selectUserStatus(global, id)?.wasOnline,
|
!isChatWithSelf && !chatBot && isUserId(id) && selectUserStatus(global, id)?.wasOnline,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectForwardsContainVoiceMessages(global: GlobalState) {
|
||||||
|
const { messageIds, fromChatId } = global.forwardMessages;
|
||||||
|
if (!messageIds) return false;
|
||||||
|
const chatMessages = selectChatMessages(global, fromChatId!);
|
||||||
|
return messageIds.some((messageId) => {
|
||||||
|
const message = chatMessages[messageId];
|
||||||
|
return Boolean(message.content.voice) || message.content.video?.isRound;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -174,6 +174,7 @@ export enum SettingsScreens {
|
|||||||
PrivacyPhoneCall,
|
PrivacyPhoneCall,
|
||||||
PrivacyPhoneP2P,
|
PrivacyPhoneP2P,
|
||||||
PrivacyForwarding,
|
PrivacyForwarding,
|
||||||
|
PrivacyVoiceMessages,
|
||||||
PrivacyGroupChats,
|
PrivacyGroupChats,
|
||||||
PrivacyPhoneNumberAllowedContacts,
|
PrivacyPhoneNumberAllowedContacts,
|
||||||
PrivacyPhoneNumberDeniedContacts,
|
PrivacyPhoneNumberDeniedContacts,
|
||||||
@ -187,6 +188,8 @@ export enum SettingsScreens {
|
|||||||
PrivacyPhoneP2PDeniedContacts,
|
PrivacyPhoneP2PDeniedContacts,
|
||||||
PrivacyForwardingAllowedContacts,
|
PrivacyForwardingAllowedContacts,
|
||||||
PrivacyForwardingDeniedContacts,
|
PrivacyForwardingDeniedContacts,
|
||||||
|
PrivacyVoiceMessagesAllowedContacts,
|
||||||
|
PrivacyVoiceMessagesDeniedContacts,
|
||||||
PrivacyGroupChatsAllowedContacts,
|
PrivacyGroupChatsAllowedContacts,
|
||||||
PrivacyGroupChatsDeniedContacts,
|
PrivacyGroupChatsDeniedContacts,
|
||||||
PrivacyBlockedUsers,
|
PrivacyBlockedUsers,
|
||||||
@ -327,7 +330,7 @@ export enum NewChatMembersProgress {
|
|||||||
|
|
||||||
export type ProfileTabType = 'members' | 'commonChats' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type ProfileTabType = 'members' | 'commonChats' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' |
|
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'voiceMessages' |
|
||||||
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P';
|
'forwards' | 'chatInvite' | 'phoneCall' | 'phoneP2P';
|
||||||
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user