Modernize ContactModal

This commit is contained in:
Josh Perez 2021-09-21 18:37:10 -04:00 committed by GitHub
parent 1d2fcde49f
commit c05d23e628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 426 additions and 493 deletions

View file

@ -58,6 +58,7 @@ import {
import { AvatarDataType, getDefaultAvatars } from '../../types/Avatar';
import { getAvatarData } from '../../util/getAvatarData';
import { isSameAvatarData } from '../../util/isSameAvatarData';
import { longRunningTaskWrapper } from '../../util/longRunningTaskWrapper';
import { NoopActionType } from './noop';
@ -780,6 +781,7 @@ export const actions = {
openConversationInternal,
removeAllConversations,
removeCustomColorOnConversations,
removeMemberFromGroup,
repairNewestMessage,
repairOldestMessage,
replaceAvatar,
@ -803,11 +805,14 @@ export const actions = {
showArchivedConversations,
showChooseGroupMembers,
showInbox,
showSafetyNumberInConversation,
startComposing,
startNewConversationFromPhoneNumber,
startSettingGroupMetadata,
toggleAdmin,
toggleConversationInChooseMembers,
toggleComposeEditingAvatar,
updateConversationModelSharedGroups,
verifyConversationsStoppingMessageSend,
};
@ -1720,6 +1725,73 @@ function openConversationExternal(
};
}
function removeMemberFromGroup(
conversationId: string,
contactId: string
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return dispatch => {
const conversationModel = window.ConversationController.get(conversationId);
if (conversationModel) {
const idForLogging = conversationModel.idForLogging();
longRunningTaskWrapper({
name: 'removeMemberFromGroup',
idForLogging,
task: () => conversationModel.removeFromGroupV2(contactId),
});
}
dispatch({
type: 'NOOP',
payload: null,
});
};
}
function toggleAdmin(
conversationId: string,
contactId: string
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return dispatch => {
const conversationModel = window.ConversationController.get(conversationId);
if (conversationModel) {
conversationModel.toggleAdmin(contactId);
}
dispatch({
type: 'NOOP',
payload: null,
});
};
}
function updateConversationModelSharedGroups(
conversationId: string
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return dispatch => {
const conversation = window.ConversationController.get(conversationId);
if (conversation && conversation.throttledUpdateSharedGroups) {
conversation.throttledUpdateSharedGroups();
}
dispatch({
type: 'NOOP',
payload: null,
});
};
}
function showSafetyNumberInConversation(
conversationId: string
): ThunkAction<void, RootStateType, unknown, NoopActionType> {
return dispatch => {
window.Whisper.events.trigger(
'showSafetyNumberInConversation',
conversationId
);
dispatch({
type: 'NOOP',
payload: null,
});
};
}
function showInbox(): ShowInboxActionType {
return {
type: 'SHOW_INBOX',

View file

@ -4,16 +4,33 @@
// State
export type GlobalModalsStateType = {
readonly contactModalState?: ContactModalStateType;
readonly isProfileEditorVisible: boolean;
readonly profileEditorHasError: boolean;
};
// Actions
const HIDE_CONTACT_MODAL = 'globalModals/HIDE_CONTACT_MODAL';
const SHOW_CONTACT_MODAL = 'globalModals/SHOW_CONTACT_MODAL';
const TOGGLE_PROFILE_EDITOR = 'globalModals/TOGGLE_PROFILE_EDITOR';
export const TOGGLE_PROFILE_EDITOR_ERROR =
'globalModals/TOGGLE_PROFILE_EDITOR_ERROR';
export type ContactModalStateType = {
contactId: string;
conversationId?: string;
};
type HideContactModalActionType = {
type: typeof HIDE_CONTACT_MODAL;
};
type ShowContactModalActionType = {
type: typeof SHOW_CONTACT_MODAL;
payload: ContactModalStateType;
};
type ToggleProfileEditorActionType = {
type: typeof TOGGLE_PROFILE_EDITOR;
};
@ -23,16 +40,39 @@ export type ToggleProfileEditorErrorActionType = {
};
export type GlobalModalsActionType =
| HideContactModalActionType
| ShowContactModalActionType
| ToggleProfileEditorActionType
| ToggleProfileEditorErrorActionType;
// Action Creators
export const actions = {
hideContactModal,
showContactModal,
toggleProfileEditor,
toggleProfileEditorHasError,
};
function hideContactModal(): HideContactModalActionType {
return {
type: HIDE_CONTACT_MODAL,
};
}
function showContactModal(
contactId: string,
conversationId?: string
): ShowContactModalActionType {
return {
type: SHOW_CONTACT_MODAL,
payload: {
contactId,
conversationId,
},
};
}
function toggleProfileEditor(): ToggleProfileEditorActionType {
return { type: TOGGLE_PROFILE_EDITOR };
}
@ -68,5 +108,19 @@ export function reducer(
};
}
if (action.type === SHOW_CONTACT_MODAL) {
return {
...state,
contactModalState: action.payload,
};
}
if (action.type === HIDE_CONTACT_MODAL) {
return {
...state,
contactModalState: undefined,
};
}
return state;
}

View file

@ -1,21 +0,0 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { Provider } from 'react-redux';
import { Store } from 'redux';
import {
SmartContactModal,
SmartContactModalProps,
} from '../smart/ContactModal';
export const createContactModal = (
store: Store,
props: SmartContactModalProps
): React.ReactElement => (
<Provider store={store}>
<SmartContactModal {...props} />
</Provider>
);

View file

@ -5,33 +5,18 @@ import { connect } from 'react-redux';
import { mapDispatchToProps } from '../actions';
import {
ContactModal,
PropsType,
PropsDataType,
} from '../../components/conversation/ContactModal';
import { StateType } from '../reducer';
import { getIntl } from '../selectors/user';
import { getConversationSelector } from '../selectors/conversations';
export type SmartContactModalProps = {
contactId: string;
currentConversationId: string;
readonly onClose: () => unknown;
readonly openConversation: (conversationId: string) => void;
readonly removeMember: (conversationId: string) => void;
readonly showSafetyNumber: (conversationId: string) => void;
readonly toggleAdmin: (conversationId: string) => void;
readonly updateSharedGroups: () => void;
};
const mapStateToProps = (state: StateType): PropsDataType => {
const { contactId, conversationId } =
state.globalModals.contactModalState || {};
const mapStateToProps = (
state: StateType,
props: SmartContactModalProps
): PropsType => {
const { contactId, currentConversationId } = props;
const currentConversation = getConversationSelector(state)(
currentConversationId
);
const currentConversation = getConversationSelector(state)(conversationId);
const contact = getConversationSelector(state)(contactId);
const areWeAdmin =
@ -51,9 +36,9 @@ const mapStateToProps = (
}
return {
...props,
areWeAdmin,
contact,
conversationId,
i18n: getIntl(state),
isAdmin,
isMember,

View file

@ -25,7 +25,6 @@ export type SmartConversationDetailsProps = {
loadRecentMediaItems: (limit: number) => void;
setDisappearingMessages: (seconds: number) => void;
showAllMedia: () => void;
showContactModal: (conversationId: string) => void;
showGroupChatColorEditor: () => void;
showGroupLinkManagement: () => void;
showGroupV2Permissions: () => void;

View file

@ -7,6 +7,7 @@ import { mapDispatchToProps } from '../actions';
import { GlobalModalContainer } from '../../components/GlobalModalContainer';
import { StateType } from '../reducer';
import { SmartProfileEditorModal } from './ProfileEditorModal';
import { SmartContactModal } from './ContactModal';
const FilteredSmartProfileEditorModal = SmartProfileEditorModal;
@ -14,9 +15,14 @@ function renderProfileEditor(): JSX.Element {
return <FilteredSmartProfileEditorModal />;
}
function renderContactModal(): JSX.Element {
return <SmartContactModal />;
}
const mapStateToProps = (state: StateType) => {
return {
...state.globalModals,
renderContactModal,
renderProfileEditor,
};
};