ConversationView: Move call/mute functions into redux
This commit is contained in:
parent
8fe51cc854
commit
92a512a16d
17 changed files with 353 additions and 287 deletions
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { Toast } from './Toast';
|
||||
|
||||
type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
onClose: () => unknown;
|
||||
};
|
||||
|
||||
export function ToastCannotStartGroupCall({
|
||||
i18n,
|
||||
onClose,
|
||||
}: PropsType): JSX.Element {
|
||||
return (
|
||||
<Toast onClose={onClose}>{i18n('GroupV2--cannot-start-group-call')}</Toast>
|
||||
);
|
||||
}
|
|
@ -30,72 +30,6 @@ export function ToastManager({
|
|||
}
|
||||
|
||||
const { toastType } = toast;
|
||||
if (toastType === ToastType.Error) {
|
||||
return (
|
||||
<Toast
|
||||
autoDismissDisabled
|
||||
onClose={hideToast}
|
||||
toastAction={{
|
||||
label: i18n('Toast--error--action'),
|
||||
onClick: () => window.showDebugLog(),
|
||||
}}
|
||||
>
|
||||
{i18n('Toast--error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.MessageBodyTooLong) {
|
||||
return <ToastMessageBodyTooLong i18n={i18n} onClose={hideToast} />;
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReact) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--sending-reaction')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReply) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--sending-reply')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryMuted) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--hasNoSound')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoTooLong) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-too-long')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoUnsupported) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-unsupported')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoError) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.AddingUserToGroup) {
|
||||
return (
|
||||
|
@ -108,21 +42,10 @@ export function ToastManager({
|
|||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.UserAddedToGroup) {
|
||||
if (toastType === ToastType.CannotStartGroupCall) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n(
|
||||
'AddUserToAnotherGroupModal__toast--user-added-to-group',
|
||||
toast.parameters
|
||||
)}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.FailedToDeleteUsername) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('ProfileEditor--username--delete-general-error')}
|
||||
{i18n('GroupV2--cannot-start-group-call', toast.parameters)}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
@ -147,5 +70,91 @@ export function ToastManager({
|
|||
return <Toast onClose={hideToast}>{i18n('deleteForEveryoneFailed')}</Toast>;
|
||||
}
|
||||
|
||||
if (toastType === ToastType.Error) {
|
||||
return (
|
||||
<Toast
|
||||
autoDismissDisabled
|
||||
onClose={hideToast}
|
||||
toastAction={{
|
||||
label: i18n('Toast--error--action'),
|
||||
onClick: () => window.showDebugLog(),
|
||||
}}
|
||||
>
|
||||
{i18n('Toast--error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.FailedToDeleteUsername) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('ProfileEditor--username--delete-general-error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.MessageBodyTooLong) {
|
||||
return <ToastMessageBodyTooLong i18n={i18n} onClose={hideToast} />;
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryMuted) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--hasNoSound')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReact) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--sending-reaction')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReply) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={SHORT_TIMEOUT}>
|
||||
{i18n('Stories__toast--sending-reply')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoError) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-error')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoTooLong) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-too-long')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryVideoUnsupported) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n('StoryCreator__error--video-unsupported')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.UserAddedToGroup) {
|
||||
return (
|
||||
<Toast onClose={hideToast}>
|
||||
{i18n(
|
||||
'AddUserToAnotherGroupModal__toast--user-added-to-group',
|
||||
toast.parameters
|
||||
)}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
throw missingCaseError(toastType);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ const commonProps = {
|
|||
setDisappearingMessages: action('setDisappearingMessages'),
|
||||
destroyMessages: action('destroyMessages'),
|
||||
onSearchInConversation: action('onSearchInConversation'),
|
||||
onSetMuteNotifications: action('onSetMuteNotifications'),
|
||||
onOutgoingAudioCallInConversation: action(
|
||||
'onOutgoingAudioCallInConversation'
|
||||
),
|
||||
|
@ -57,6 +56,7 @@ const commonProps = {
|
|||
onMarkUnread: action('onMarkUnread'),
|
||||
onMoveToInbox: action('onMoveToInbox'),
|
||||
onSetPin: action('onSetPin'),
|
||||
setMuteExpiration: action('onSetMuteNotifications'),
|
||||
viewUserStories: action('viewUserStories'),
|
||||
};
|
||||
|
||||
|
|
|
@ -80,11 +80,10 @@ export type PropsDataType = {
|
|||
>;
|
||||
|
||||
export type PropsActionsType = {
|
||||
onSetMuteNotifications: (seconds: number) => void;
|
||||
destroyMessages: (conversationId: string) => void;
|
||||
onSearchInConversation: () => void;
|
||||
onOutgoingAudioCallInConversation: () => void;
|
||||
onOutgoingVideoCallInConversation: () => void;
|
||||
onOutgoingAudioCallInConversation: (conversationId: string) => void;
|
||||
onOutgoingVideoCallInConversation: (conversationId: string) => void;
|
||||
onSetPin: (value: boolean) => void;
|
||||
|
||||
onShowConversationDetails: () => void;
|
||||
|
@ -95,6 +94,7 @@ export type PropsActionsType = {
|
|||
onArchive: () => void;
|
||||
onMarkUnread: () => void;
|
||||
onMoveToInbox: () => void;
|
||||
setMuteExpiration: (conversationId: string, seconds: number) => void;
|
||||
setDisappearingMessages: (
|
||||
conversationId: string,
|
||||
seconds: DurationInSeconds
|
||||
|
@ -349,12 +349,12 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
|||
onArchive,
|
||||
onMarkUnread,
|
||||
onMoveToInbox,
|
||||
onSetMuteNotifications,
|
||||
onSetPin,
|
||||
onShowAllMedia,
|
||||
onShowConversationDetails,
|
||||
onShowGroupMembers,
|
||||
setDisappearingMessages,
|
||||
setMuteExpiration,
|
||||
type,
|
||||
} = this.props;
|
||||
|
||||
|
@ -371,7 +371,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
|||
{isMuted ? (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
onSetMuteNotifications(0);
|
||||
setMuteExpiration(id, 0);
|
||||
}}
|
||||
>
|
||||
{i18n('unmute')}
|
||||
|
@ -379,7 +379,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
|||
) : (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
onSetMuteNotifications(Number.MAX_SAFE_INTEGER);
|
||||
setMuteExpiration(id, Number.MAX_SAFE_INTEGER);
|
||||
}}
|
||||
>
|
||||
{i18n('muteAlways')}
|
||||
|
@ -465,7 +465,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
|||
key={item.name}
|
||||
disabled={item.disabled}
|
||||
onClick={() => {
|
||||
onSetMuteNotifications(item.value);
|
||||
setMuteExpiration(id, item.value);
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
|
@ -676,6 +676,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
|||
announcementsOnly={announcementsOnly}
|
||||
areWeAdmin={areWeAdmin}
|
||||
i18n={i18n}
|
||||
id={id}
|
||||
isNarrow={isNarrow}
|
||||
onOutgoingAudioCallInConversation={
|
||||
onOutgoingAudioCallInConversation
|
||||
|
@ -702,6 +703,7 @@ function OutgoingCallButtons({
|
|||
announcementsOnly,
|
||||
areWeAdmin,
|
||||
i18n,
|
||||
id,
|
||||
isNarrow,
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation,
|
||||
|
@ -712,6 +714,7 @@ function OutgoingCallButtons({
|
|||
| 'announcementsOnly'
|
||||
| 'areWeAdmin'
|
||||
| 'i18n'
|
||||
| 'id'
|
||||
| 'onOutgoingAudioCallInConversation'
|
||||
| 'onOutgoingVideoCallInConversation'
|
||||
| 'outgoingCallButtonStyle'
|
||||
|
@ -729,14 +732,14 @@ function OutgoingCallButtons({
|
|||
: undefined
|
||||
)}
|
||||
disabled={showBackButton}
|
||||
onClick={onOutgoingVideoCallInConversation}
|
||||
onClick={() => onOutgoingVideoCallInConversation(id)}
|
||||
type="button"
|
||||
/>
|
||||
);
|
||||
|
||||
const startCallShortcuts = useStartCallShortcuts(
|
||||
onOutgoingAudioCallInConversation,
|
||||
onOutgoingVideoCallInConversation
|
||||
() => onOutgoingAudioCallInConversation(id),
|
||||
() => onOutgoingVideoCallInConversation(id)
|
||||
);
|
||||
useKeyboardShortcuts(startCallShortcuts);
|
||||
|
||||
|
@ -751,7 +754,7 @@ function OutgoingCallButtons({
|
|||
{videoButton}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOutgoingAudioCallInConversation}
|
||||
onClick={() => onOutgoingAudioCallInConversation(id)}
|
||||
className={classNames(
|
||||
'module-ConversationHeader__button',
|
||||
'module-ConversationHeader__button--audio',
|
||||
|
@ -772,7 +775,7 @@ function OutgoingCallButtons({
|
|||
showBackButton ? null : 'module-ConversationHeader__button--show'
|
||||
)}
|
||||
disabled={showBackButton}
|
||||
onClick={onOutgoingVideoCallInConversation}
|
||||
onClick={() => onOutgoingVideoCallInConversation(id)}
|
||||
type="button"
|
||||
>
|
||||
{isNarrow ? null : i18n('joinOngoingCall')}
|
||||
|
|
|
@ -101,9 +101,6 @@ export type StateProps = {
|
|||
onUnblock: () => void;
|
||||
theme: ThemeType;
|
||||
userAvatarData: Array<AvatarDataType>;
|
||||
setMuteExpiration: (muteExpiresAt: undefined | number) => unknown;
|
||||
onOutgoingAudioCallInConversation: () => unknown;
|
||||
onOutgoingVideoCallInConversation: () => unknown;
|
||||
renderChooseGroupMembersModal: (
|
||||
props: SmartChooseGroupMembersModalPropsType
|
||||
) => JSX.Element;
|
||||
|
@ -115,10 +112,13 @@ export type StateProps = {
|
|||
type ActionProps = {
|
||||
deleteAvatarFromDisk: DeleteAvatarFromDiskActionType;
|
||||
loadRecentMediaItems: (id: string, limit: number) => void;
|
||||
onOutgoingAudioCallInConversation: (conversationId: string) => unknown;
|
||||
onOutgoingVideoCallInConversation: (conversationId: string) => unknown;
|
||||
replaceAvatar: ReplaceAvatarActionType;
|
||||
saveAvatarToDisk: SaveAvatarToDiskActionType;
|
||||
searchInConversation: (id: string) => unknown;
|
||||
setDisappearingMessages: (id: string, seconds: DurationInSeconds) => void;
|
||||
setMuteExpiration: (id: string, muteExpiresAt: undefined | number) => unknown;
|
||||
showContactModal: (contactId: string, conversationId?: string) => void;
|
||||
showConversation: ShowConversationType;
|
||||
toggleAddUserToAnotherGroupModal: (contactId?: string) => void;
|
||||
|
@ -291,6 +291,7 @@ export function ConversationDetails({
|
|||
modalNode = (
|
||||
<ConversationNotificationsModal
|
||||
i18n={i18n}
|
||||
id={conversation.id}
|
||||
muteExpiresAt={conversation.muteExpiresAt}
|
||||
onClose={() => {
|
||||
setModalState(ModalState.NothingOpen);
|
||||
|
@ -305,7 +306,7 @@ export function ConversationDetails({
|
|||
dialogName="ConversationDetails.unmuteNotifications"
|
||||
actions={[
|
||||
{
|
||||
action: () => setMuteExpiration(0),
|
||||
action: () => setMuteExpiration(conversation.id, 0),
|
||||
style: 'affirmative',
|
||||
text: i18n('unmute'),
|
||||
},
|
||||
|
@ -354,14 +355,16 @@ export function ConversationDetails({
|
|||
<ConversationDetailsCallButton
|
||||
disabled={hasActiveCall}
|
||||
i18n={i18n}
|
||||
onClick={onOutgoingVideoCallInConversation}
|
||||
onClick={() => onOutgoingVideoCallInConversation(conversation.id)}
|
||||
type="video"
|
||||
/>
|
||||
{!isGroup && (
|
||||
<ConversationDetailsCallButton
|
||||
disabled={hasActiveCall}
|
||||
i18n={i18n}
|
||||
onClick={onOutgoingAudioCallInConversation}
|
||||
onClick={() =>
|
||||
onOutgoingAudioCallInConversation(conversation.id)
|
||||
}
|
||||
type="audio"
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -12,13 +12,18 @@ import { Button, ButtonVariant } from '../../Button';
|
|||
|
||||
type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
id: string;
|
||||
muteExpiresAt: undefined | number;
|
||||
onClose: () => unknown;
|
||||
setMuteExpiration: (muteExpiresAt: undefined | number) => unknown;
|
||||
setMuteExpiration: (
|
||||
conversationId: string,
|
||||
muteExpiresAt: undefined | number
|
||||
) => unknown;
|
||||
};
|
||||
|
||||
export function ConversationNotificationsModal({
|
||||
i18n,
|
||||
id,
|
||||
muteExpiresAt,
|
||||
onClose,
|
||||
setMuteExpiration,
|
||||
|
@ -40,7 +45,7 @@ export function ConversationNotificationsModal({
|
|||
muteExpirationValue,
|
||||
'NotificationSettings: mute ms was not an integer'
|
||||
);
|
||||
setMuteExpiration(ms);
|
||||
setMuteExpiration(id, ms);
|
||||
onClose();
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ export default {
|
|||
};
|
||||
|
||||
const getCommonProps = () => ({
|
||||
id: 'conversation-id',
|
||||
muteExpiresAt: undefined,
|
||||
conversationType: 'group' as const,
|
||||
dontNotifyForMentionsIfMuted: false,
|
||||
|
|
|
@ -15,17 +15,23 @@ import { parseIntOrThrow } from '../../../util/parseIntOrThrow';
|
|||
import { useUniqueId } from '../../../hooks/useUniqueId';
|
||||
|
||||
type PropsType = {
|
||||
id: string;
|
||||
conversationType: ConversationTypeType;
|
||||
dontNotifyForMentionsIfMuted: boolean;
|
||||
i18n: LocalizerType;
|
||||
muteExpiresAt: undefined | number;
|
||||
setDontNotifyForMentionsIfMuted: (
|
||||
conversationId: string,
|
||||
dontNotifyForMentionsIfMuted: boolean
|
||||
) => unknown;
|
||||
setMuteExpiration: (muteExpiresAt: undefined | number) => unknown;
|
||||
setMuteExpiration: (
|
||||
conversationId: string,
|
||||
muteExpiresAt: undefined | number
|
||||
) => unknown;
|
||||
};
|
||||
|
||||
export function ConversationNotificationsSettings({
|
||||
id,
|
||||
conversationType,
|
||||
dontNotifyForMentionsIfMuted,
|
||||
i18n,
|
||||
|
@ -62,11 +68,11 @@ export function ConversationNotificationsSettings({
|
|||
rawValue,
|
||||
'NotificationSettings: mute ms was not an integer'
|
||||
);
|
||||
setMuteExpiration(ms);
|
||||
setMuteExpiration(id, ms);
|
||||
};
|
||||
|
||||
const onChangeDontNotifyForMentionsIfMuted = (rawValue: string) => {
|
||||
setDontNotifyForMentionsIfMuted(rawValue === 'yes');
|
||||
setDontNotifyForMentionsIfMuted(id, rawValue === 'yes');
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue