reduxify remaining dialogs

pull/1703/head
Audric Ackermann 4 years ago
parent 93e43fe929
commit 651921590c
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -12,12 +12,10 @@ const LinkPreviews = require('./link_previews');
const { Message } = require('../../ts/components/conversation/Message'); const { Message } = require('../../ts/components/conversation/Message');
// Components // Components
const { SessionSeedModal } = require('../../ts/components/session/SessionSeedModal');
const { SessionIDResetDialog } = require('../../ts/components/session/SessionIDResetDialog'); const { SessionIDResetDialog } = require('../../ts/components/session/SessionIDResetDialog');
const { SessionRegistrationView } = require('../../ts/components/session/SessionRegistrationView'); const { SessionRegistrationView } = require('../../ts/components/session/SessionRegistrationView');
const { SessionInboxView } = require('../../ts/components/session/SessionInboxView'); const { SessionInboxView } = require('../../ts/components/session/SessionInboxView');
const { SessionPasswordModal } = require('../../ts/components/session/SessionPasswordModal');
// Types // Types
const AttachmentType = require('./types/attachment'); const AttachmentType = require('./types/attachment');
@ -123,9 +121,7 @@ exports.setup = (options = {}) => {
const Components = { const Components = {
SessionInboxView, SessionInboxView,
SessionSeedModal,
SessionIDResetDialog, SessionIDResetDialog,
SessionPasswordModal,
SessionRegistrationView, SessionRegistrationView,
Message, Message,
}; };

@ -9,24 +9,16 @@ import { SessionButton, SessionButtonColor, SessionButtonType } from './session/
import { SessionIconButton, SessionIconSize, SessionIconType } from './session/icon'; import { SessionIconButton, SessionIconSize, SessionIconType } from './session/icon';
import { PillDivider } from './session/PillDivider'; import { PillDivider } from './session/PillDivider';
import { SyncUtils, ToastUtils, UserUtils } from '../session/utils'; import { SyncUtils, ToastUtils, UserUtils } from '../session/utils';
import { DefaultTheme } from 'styled-components';
import { MAX_USERNAME_LENGTH } from './session/registration/RegistrationTabs'; import { MAX_USERNAME_LENGTH } from './session/registration/RegistrationTabs';
import { SessionSpinner } from './session/SessionSpinner'; import { SessionSpinner } from './session/SessionSpinner';
import { ConversationTypeEnum } from '../models/conversation'; import { ConversationModel, ConversationTypeEnum } from '../models/conversation';
import { SessionWrapperModal } from './session/SessionWrapperModal'; import { SessionWrapperModal } from './session/SessionWrapperModal';
import { AttachmentUtil } from '../util'; import { AttachmentUtil } from '../util';
import { ConversationController } from '../session/conversations'; import { ConversationController } from '../session/conversations';
import { SpacerLG, SpacerMD } from './basic/Text'; import { SpacerLG, SpacerMD } from './basic/Text';
import autoBind from 'auto-bind';
interface Props { import { editProfileModal } from '../state/ducks/modalDialog';
profileName?: string;
avatarPath?: string;
pubkey?: string;
onClose?: any;
onOk?: any;
theme: DefaultTheme;
}
interface State { interface State {
profileName: string; profileName: string;
@ -36,23 +28,21 @@ interface State {
loading: boolean; loading: boolean;
} }
export class EditProfileDialog extends React.Component<Props, State> { export class EditProfileDialog extends React.Component<{}, State> {
private readonly inputEl: any; private readonly inputEl: any;
private readonly convo: ConversationModel;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
this.onNameEdited = this.onNameEdited.bind(this); autoBind(this);
this.closeDialog = this.closeDialog.bind(this);
this.onClickOK = this.onClickOK.bind(this); this.convo = ConversationController.getInstance().get(UserUtils.getOurPubKeyStrFromCache());
this.onKeyUp = this.onKeyUp.bind(this);
this.onFileSelected = this.onFileSelected.bind(this);
this.fireInputEvent = this.fireInputEvent.bind(this);
this.state = { this.state = {
profileName: this.props.profileName || '', profileName: this.convo.getProfileName() || '',
setProfileName: this.props.profileName || '', setProfileName: this.convo.getProfileName() || '',
avatar: this.props.avatarPath || '', avatar: this.convo.getAvatarPath() || '',
mode: 'default', mode: 'default',
loading: false, loading: false,
}; };
@ -98,7 +88,6 @@ export class EditProfileDialog extends React.Component<Props, State> {
} }
public render() { public render() {
// const i18n = this.props.i18n;
const i18n = window.i18n; const i18n = window.i18n;
const viewDefault = this.state.mode === 'default'; const viewDefault = this.state.mode === 'default';
@ -194,7 +183,6 @@ export class EditProfileDialog extends React.Component<Props, State> {
onClick={() => { onClick={() => {
this.setState({ mode: 'qr' }); this.setState({ mode: 'qr' });
}} }}
theme={this.props.theme}
/> />
</div> </div>
</div> </div>
@ -226,7 +214,6 @@ export class EditProfileDialog extends React.Component<Props, State> {
onClick={() => { onClick={() => {
this.setState({ mode: 'edit' }); this.setState({ mode: 'edit' });
}} }}
theme={this.props.theme}
/> />
</div> </div>
</> </>
@ -278,10 +265,11 @@ export class EditProfileDialog extends React.Component<Props, State> {
private renderAvatar() { private renderAvatar() {
const { avatar, profileName } = this.state; const { avatar, profileName } = this.state;
const { pubkey } = this.props; const userName = profileName || this.convo.id;
const userName = profileName || pubkey;
return <Avatar avatarPath={avatar} name={userName} size={AvatarSize.XL} pubkey={pubkey} />; return (
<Avatar avatarPath={avatar} name={userName} size={AvatarSize.XL} pubkey={this.convo.id} />
);
} }
private onNameEdited(event: any) { private onNameEdited(event: any) {
@ -299,7 +287,6 @@ export class EditProfileDialog extends React.Component<Props, State> {
switch (event.key) { switch (event.key) {
case 'Enter': case 'Enter':
if (this.state.mode === 'edit') { if (this.state.mode === 'edit') {
// this.onClickOK();
this.onClickOK(); this.onClickOK();
} }
break; break;
@ -353,7 +340,7 @@ export class EditProfileDialog extends React.Component<Props, State> {
private closeDialog() { private closeDialog() {
window.removeEventListener('keyup', this.onKeyUp); window.removeEventListener('keyup', this.onKeyUp);
this.props.onClose(); window.inboxStore?.dispatch(editProfileModal(null));
} }
private async commitProfileEdits(newName: string, avatar: any) { private async commitProfileEdits(newName: string, avatar: any) {

@ -86,9 +86,8 @@ const InnerLeftPaneContactSection = () => {
); );
}; };
const LeftPaneSection = (props: { isExpired: boolean; setModal: any }) => { const LeftPaneSection = (props: { isExpired: boolean }) => {
const focusedSection = useSelector(getFocusedSection); const focusedSection = useSelector(getFocusedSection);
const { setModal } = props;
if (focusedSection === SectionType.Message) { if (focusedSection === SectionType.Message) {
return <InnerLeftPaneMessageSection isExpired={props.isExpired} />; return <InnerLeftPaneMessageSection isExpired={props.isExpired} />;
@ -98,7 +97,7 @@ const LeftPaneSection = (props: { isExpired: boolean; setModal: any }) => {
return <InnerLeftPaneContactSection />; return <InnerLeftPaneContactSection />;
} }
if (focusedSection === SectionType.Settings) { if (focusedSection === SectionType.Settings) {
return <LeftPaneSettingSection setModal={setModal} />; return <LeftPaneSettingSection />;
} }
return <></>; return <></>;
}; };
@ -106,17 +105,14 @@ const LeftPaneSection = (props: { isExpired: boolean; setModal: any }) => {
export const LeftPane = (props: Props) => { export const LeftPane = (props: Props) => {
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
const [modal, setModal] = useState<any>(null);
return ( return (
<> <>
{modal ? modal : null}
<SessionTheme theme={theme}> <SessionTheme theme={theme}>
<div className="module-left-pane-session"> <div className="module-left-pane-session">
<ActionsPanel /> <ActionsPanel />
<div className="module-left-pane"> <div className="module-left-pane">
<LeftPaneSection setModal={setModal} isExpired={props.isExpired} /> <LeftPaneSection isExpired={props.isExpired} />
</div> </div>
</div> </div>
</SessionTheme> </SessionTheme>

@ -9,6 +9,7 @@ import { SessionWrapperModal } from './session/SessionWrapperModal';
import { SpacerMD } from './basic/Text'; import { SpacerMD } from './basic/Text';
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import { updateUserDetailsModal } from '../state/ducks/modalDialog'; import { updateUserDetailsModal } from '../state/ducks/modalDialog';
import { openConversationExternal } from '../state/ducks/conversations';
type Props = { type Props = {
conversationId: string; conversationId: string;
@ -99,7 +100,7 @@ export class UserDetailsDialog extends React.Component<Props, State> {
ConversationTypeEnum.PRIVATE ConversationTypeEnum.PRIVATE
); );
window.inboxStore?.dispatch(window.actionsCreators.openConversationExternal(conversation.id)); window.inboxStore?.dispatch(openConversationExternal(conversation.id));
this.closeDialog(); this.closeDialog();
} }

@ -1,32 +1,31 @@
import React from 'react'; import React from 'react';
import { SessionButton, SessionButtonColor } from '../session/SessionButton'; import { SessionButton, SessionButtonColor } from '../session/SessionButton';
import { DefaultTheme } from 'styled-components';
import { SessionWrapperModal } from '../session/SessionWrapperModal'; import { SessionWrapperModal } from '../session/SessionWrapperModal';
import { SpacerLG } from '../basic/Text'; import { SpacerLG } from '../basic/Text';
import { ConversationController } from '../../session/conversations';
import { adminLeaveClosedGroup } from '../../state/ducks/modalDialog';
type Props = { type Props = {
groupName: string; conversationId: string;
onSubmit: () => any;
onClose: any;
theme: DefaultTheme;
}; };
const AdminLeaveClosedGroupDialogInner = (props: Props) => { export const AdminLeaveClosedGroupDialog = (props: Props) => {
const { groupName, theme, onSubmit, onClose } = props; const convo = ConversationController.getInstance().get(props.conversationId);
const titleText = `${window.i18n('leaveGroup')} ${convo.getName()}`;
const titleText = `${window.i18n('leaveGroup')} ${groupName}`;
const warningAsAdmin = `${window.i18n('leaveGroupConfirmationAdmin')}`; const warningAsAdmin = `${window.i18n('leaveGroupConfirmationAdmin')}`;
const okText = window.i18n('leaveAndRemoveForEveryone'); const okText = window.i18n('leaveAndRemoveForEveryone');
const cancelText = window.i18n('cancel'); const cancelText = window.i18n('cancel');
const onClickOK = () => { const onClickOK = async () => {
void onSubmit(); await ConversationController.getInstance()
.get(props.conversationId)
.leaveClosedGroup();
closeDialog(); closeDialog();
}; };
const closeDialog = () => { const closeDialog = () => {
onClose(); window.inboxStore?.dispatch(adminLeaveClosedGroup(null));
}; };
return ( return (
@ -41,5 +40,3 @@ const AdminLeaveClosedGroupDialogInner = (props: Props) => {
</SessionWrapperModal> </SessionWrapperModal>
); );
}; };
export const AdminLeaveClosedGroupDialog = AdminLeaveClosedGroupDialogInner;

@ -50,8 +50,13 @@ import { EditProfileDialog } from '../EditProfileDialog';
import { SessionConfirm } from './SessionConfirm'; import { SessionConfirm } from './SessionConfirm';
import { import {
getAddModeratorsModal, getAddModeratorsModal,
getAdminLeaveClosedGroupDialog,
getChangeNickNameDialog,
getConfirmModal, getConfirmModal,
getEditProfileDialog,
getInviteContactModal, getInviteContactModal,
getOnionPathDialog,
getRecoveryPhraseDialog,
getRemoveModeratorsModal, getRemoveModeratorsModal,
getUpdateGroupMembersModal, getUpdateGroupMembersModal,
getUpdateGroupNameModal, getUpdateGroupNameModal,
@ -63,6 +68,10 @@ import { RemoveModeratorsDialog } from '../conversation/ModeratorsRemoveDialog';
import { UpdateGroupNameDialog } from '../conversation/UpdateGroupNameDialog'; import { UpdateGroupNameDialog } from '../conversation/UpdateGroupNameDialog';
import { UpdateGroupMembersDialog } from '../conversation/UpdateGroupMembersDialog'; import { UpdateGroupMembersDialog } from '../conversation/UpdateGroupMembersDialog';
import { UserDetailsDialog } from '../UserDetailsDialog'; import { UserDetailsDialog } from '../UserDetailsDialog';
import { SessionNicknameDialog } from './SessionNicknameDialog';
import { editProfileModal, onionPathModal } from '../../state/ducks/modalDialog';
import { SessionSeedModal } from './SessionSeedModal';
import { AdminLeaveClosedGroupDialog } from '../conversation/AdminLeaveClosedGroupDialog';
// tslint:disable-next-line: no-import-side-effect no-submodule-imports // tslint:disable-next-line: no-import-side-effect no-submodule-imports
@ -76,24 +85,20 @@ export enum SectionType {
PathIndicator, PathIndicator,
} }
const Section = (props: { setModal?: any; type: SectionType; avatarPath?: string }) => { const Section = (props: { type: SectionType; avatarPath?: string }) => {
const ourNumber = useSelector(getOurNumber); const ourNumber = useSelector(getOurNumber);
const unreadMessageCount = useSelector(getUnreadMessageCount); const unreadMessageCount = useSelector(getUnreadMessageCount);
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { setModal, type, avatarPath } = props; const { type, avatarPath } = props;
const focusedSection = useSelector(getFocusedSection); const focusedSection = useSelector(getFocusedSection);
const isSelected = focusedSection === props.type; const isSelected = focusedSection === props.type;
const handleModalClose = () => {
setModal(null);
};
const handleClick = () => { const handleClick = () => {
/* tslint:disable:no-void-expression */ /* tslint:disable:no-void-expression */
if (type === SectionType.Profile) { if (type === SectionType.Profile) {
setModal(<EditProfileDialog onClose={handleModalClose} theme={theme} />); dispatch(editProfileModal({}));
} else if (type === SectionType.Moon) { } else if (type === SectionType.Moon) {
const themeFromSettings = window.Events.getThemeSetting(); const themeFromSettings = window.Events.getThemeSetting();
const updatedTheme = themeFromSettings === 'dark' ? 'light' : 'dark'; const updatedTheme = themeFromSettings === 'dark' ? 'light' : 'dark';
@ -103,7 +108,7 @@ const Section = (props: { setModal?: any; type: SectionType; avatarPath?: string
dispatch(applyTheme(newThemeObject)); dispatch(applyTheme(newThemeObject));
} else if (type === SectionType.PathIndicator) { } else if (type === SectionType.PathIndicator) {
// Show Path Indicator Modal // Show Path Indicator Modal
setModal(<OnionPathModal onClose={handleModalClose} />); dispatch(onionPathModal({}));
} else { } else {
dispatch(clearSearch()); dispatch(clearSearch());
dispatch(showLeftPaneSection(type)); dispatch(showLeftPaneSection(type));
@ -346,9 +351,14 @@ const ModalContainer = () => {
const updateGroupMembersModalState = useSelector(getUpdateGroupMembersModal); const updateGroupMembersModalState = useSelector(getUpdateGroupMembersModal);
const updateGroupNameModalState = useSelector(getUpdateGroupNameModal); const updateGroupNameModalState = useSelector(getUpdateGroupNameModal);
const userDetailsModalState = useSelector(getUserDetailsModal); const userDetailsModalState = useSelector(getUserDetailsModal);
const changeNicknameModal = useSelector(getChangeNickNameDialog);
const editProfileModalState = useSelector(getEditProfileDialog);
const onionPathModalState = useSelector(getOnionPathDialog);
const recoveryPhraseModalState = useSelector(getRecoveryPhraseDialog);
const adminLeaveClosedGroupModalState = useSelector(getAdminLeaveClosedGroupDialog);
return ( return (
<React.Fragment> <>
{confirmModalState && <SessionConfirm {...confirmModalState} />} {confirmModalState && <SessionConfirm {...confirmModalState} />}
{inviteModalState && <InviteContactsDialog {...inviteModalState} />} {inviteModalState && <InviteContactsDialog {...inviteModalState} />}
{addModeratorsModalState && <AddModeratorsDialog {...addModeratorsModalState} />} {addModeratorsModalState && <AddModeratorsDialog {...addModeratorsModalState} />}
@ -358,7 +368,14 @@ const ModalContainer = () => {
)} )}
{updateGroupNameModalState && <UpdateGroupNameDialog {...updateGroupNameModalState} />} {updateGroupNameModalState && <UpdateGroupNameDialog {...updateGroupNameModalState} />}
{userDetailsModalState && <UserDetailsDialog {...userDetailsModalState} />} {userDetailsModalState && <UserDetailsDialog {...userDetailsModalState} />}
</React.Fragment> {changeNicknameModal && <SessionNicknameDialog {...changeNicknameModal} />}
{editProfileModalState && <EditProfileDialog {...editProfileModalState} />}
{onionPathModalState && <OnionPathModal {...onionPathModalState} />}
{recoveryPhraseModalState && <SessionSeedModal {...recoveryPhraseModalState} />}
{adminLeaveClosedGroupModalState && (
<AdminLeaveClosedGroupDialog {...adminLeaveClosedGroupModalState} />
)}
</>
); );
}; };
@ -369,7 +386,6 @@ const ModalContainer = () => {
export const ActionsPanel = () => { export const ActionsPanel = () => {
const [startCleanUpMedia, setStartCleanUpMedia] = useState(false); const [startCleanUpMedia, setStartCleanUpMedia] = useState(false);
const ourPrimaryConversation = useSelector(getOurPrimaryConversation); const ourPrimaryConversation = useSelector(getOurPrimaryConversation);
const [modal, setModal] = useState<any>(null);
// this maxi useEffect is called only once: when the component is mounted. // this maxi useEffect is called only once: when the component is mounted.
// For the action panel, it means this is called only one per app start/with a user loggedin // For the action panel, it means this is called only one per app start/with a user loggedin
@ -412,21 +428,16 @@ export const ActionsPanel = () => {
return ( return (
<> <>
{modal && modal}
<ModalContainer /> <ModalContainer />
<div className="module-left-pane__sections-container"> <div className="module-left-pane__sections-container">
<Section <Section type={SectionType.Profile} avatarPath={ourPrimaryConversation.avatarPath} />
setModal={setModal}
type={SectionType.Profile}
avatarPath={ourPrimaryConversation.avatarPath}
/>
<Section type={SectionType.Message} /> <Section type={SectionType.Message} />
<Section type={SectionType.Contact} /> <Section type={SectionType.Contact} />
<Section type={SectionType.Settings} /> <Section type={SectionType.Settings} />
<SessionToastContainer /> <SessionToastContainer />
<Section setModal={setModal} type={SectionType.PathIndicator} /> <Section type={SectionType.PathIndicator} />
<Section type={SectionType.Moon} /> <Section type={SectionType.Moon} />
</div> </div>
</> </>

@ -62,7 +62,6 @@ interface State {
loading: boolean; loading: boolean;
overlay: false | SessionComposeToType; overlay: false | SessionComposeToType;
valuePasted: string; valuePasted: string;
modal: null | JSX.Element;
} }
export class LeftPaneMessageSection extends React.Component<Props, State> { export class LeftPaneMessageSection extends React.Component<Props, State> {
@ -75,7 +74,6 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
loading: false, loading: false,
overlay: false, overlay: false,
valuePasted: '', valuePasted: '',
modal: null,
}; };
autoBind(this); autoBind(this);
@ -169,18 +167,11 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
return ( return (
<div className="session-left-pane-section-content"> <div className="session-left-pane-section-content">
{this.renderHeader()} {this.renderHeader()}
{this.state.modal ? this.state.modal : null}
{overlay ? this.renderClosableOverlay(overlay) : this.renderConversations()} {overlay ? this.renderClosableOverlay(overlay) : this.renderConversations()}
</div> </div>
); );
} }
public setModal(modal: null | JSX.Element) {
this.setState({
modal,
});
}
public renderConversations() { public renderConversations() {
return ( return (
<div className="module-conversations-list-content"> <div className="module-conversations-list-content">

@ -14,6 +14,7 @@ import { getFocusedSettingsSection } from '../../state/selectors/section';
import { getTheme } from '../../state/selectors/theme'; import { getTheme } from '../../state/selectors/theme';
import { SessionConfirm } from './SessionConfirm'; import { SessionConfirm } from './SessionConfirm';
import { SessionSeedModal } from './SessionSeedModal'; import { SessionSeedModal } from './SessionSeedModal';
import { recoveryPhraseModal, updateConfirmModal } from '../../state/ducks/modalDialog';
type Props = { type Props = {
settingsCategory: SessionSettingCategory; settingsCategory: SessionSettingCategory;
@ -104,37 +105,33 @@ const LeftPaneSettingsCategories = () => {
); );
}; };
const onDeleteAccount = (setModal: any) => { const onDeleteAccount = () => {
const title = window.i18n('clearAllData'); const title = window.i18n('clearAllData');
const message = window.i18n('deleteAccountWarning'); const message = window.i18n('deleteAccountWarning');
const clearModal = () => { const onClickClose = () => {
setModal(null); window.inboxStore?.dispatch(updateConfirmModal(null));
}; };
setModal( window.inboxStore?.dispatch(
<SessionConfirm updateConfirmModal({
title={title} title,
message={message} message,
onClickOk={deleteAccount} okTheme: SessionButtonColor.Danger,
okTheme={SessionButtonColor.Danger} onClickOk: deleteAccount,
onClickClose={clearModal} onClickClose,
/> closeAfterClickOk: true,
})
); );
}; };
const onShowRecoverPhrase = (setModal: any) => { const onShowRecoveryPhrase = () => {
const clearModal = () => { window.inboxStore?.dispatch(recoveryPhraseModal({}));
setModal(null);
};
setModal(<SessionSeedModal onClose={clearModal} />);
}; };
const LeftPaneBottomButtons = (props: { setModal: any }) => { const LeftPaneBottomButtons = () => {
const dangerButtonText = window.i18n('clearAllData'); const dangerButtonText = window.i18n('clearAllData');
const showRecoveryPhrase = window.i18n('showRecoveryPhrase'); const showRecoveryPhrase = window.i18n('showRecoveryPhrase');
const { setModal } = props;
return ( return (
<div className="left-pane-setting-bottom-buttons"> <div className="left-pane-setting-bottom-buttons">
@ -143,7 +140,7 @@ const LeftPaneBottomButtons = (props: { setModal: any }) => {
buttonType={SessionButtonType.SquareOutline} buttonType={SessionButtonType.SquareOutline}
buttonColor={SessionButtonColor.Danger} buttonColor={SessionButtonColor.Danger}
onClick={() => { onClick={() => {
onDeleteAccount(setModal); onDeleteAccount();
}} }}
/> />
@ -152,23 +149,21 @@ const LeftPaneBottomButtons = (props: { setModal: any }) => {
buttonType={SessionButtonType.SquareOutline} buttonType={SessionButtonType.SquareOutline}
buttonColor={SessionButtonColor.White} buttonColor={SessionButtonColor.White}
onClick={() => { onClick={() => {
onShowRecoverPhrase(setModal); onShowRecoveryPhrase();
}} }}
/> />
</div> </div>
); );
}; };
export const LeftPaneSettingSection = (props: { setModal: any }) => { export const LeftPaneSettingSection = () => {
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
const { setModal } = props;
return ( return (
<div className="left-pane-setting-section"> <div className="left-pane-setting-section">
<LeftPaneSectionHeader label={window.i18n('settingsHeader')} theme={theme} /> <LeftPaneSectionHeader label={window.i18n('settingsHeader')} theme={theme} />
<div className="left-pane-setting-content"> <div className="left-pane-setting-content">
<LeftPaneSettingsCategories /> <LeftPaneSettingsCategories />
<LeftPaneBottomButtons setModal={setModal} /> <LeftPaneBottomButtons />
</div> </div>
</div> </div>
); );

@ -1,25 +1,22 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ConversationController } from '../../session/conversations/ConversationController'; import { ConversationController } from '../../session/conversations/ConversationController';
import { SessionButton } from './SessionButton'; import { SessionButton } from './SessionButton';
import { DefaultTheme, useTheme, withTheme } from 'styled-components';
import _ from 'lodash'; import _ from 'lodash';
import { SessionWrapperModal } from './SessionWrapperModal'; import { SessionWrapperModal } from './SessionWrapperModal';
import { SpacerLG } from '../basic/Text'; import { SpacerLG } from '../basic/Text';
import { useDispatch } from 'react-redux';
import { changeNickNameModal } from '../../state/ducks/modalDialog';
type Props = { type Props = {
onClickOk?: any; conversationId: string;
onClickClose?: any;
theme?: DefaultTheme;
conversationId?: string;
}; };
const SessionNicknameInner = (props: Props) => { export const SessionNicknameDialog = (props: Props) => {
const { onClickOk, onClickClose, conversationId } = props; const { conversationId } = props;
let { theme } = props;
const [nickname, setNickname] = useState(''); const [nickname, setNickname] = useState('');
theme = theme ? theme : useTheme(); const dispatch = useDispatch();
/** /**
* Changes the state of nickname variable. If enter is pressed, saves the current * Changes the state of nickname variable. If enter is pressed, saves the current
@ -34,6 +31,10 @@ const SessionNicknameInner = (props: Props) => {
} }
}; };
const onClickClose = () => {
dispatch(changeNickNameModal(null));
};
/** /**
* Saves the currently entered nickname. * Saves the currently entered nickname.
*/ */
@ -42,23 +43,11 @@ const SessionNicknameInner = (props: Props) => {
throw new Error('Cant save without conversation id'); throw new Error('Cant save without conversation id');
} }
const conversation = ConversationController.getInstance().get(conversationId); const conversation = ConversationController.getInstance().get(conversationId);
if (onClickOk) {
onClickOk(nickname);
}
await conversation.setNickname(nickname); await conversation.setNickname(nickname);
onClickClose(); onClickClose();
}; };
return ( return (
// <SessionModal
// title={window.i18n('changeNickname')}
// onClose={onClickClose}
// showExitIcon={false}
// showHeader={true}
// theme={theme}
// >
// TODO: Implement showHeader option for modal
<SessionWrapperModal <SessionWrapperModal
title={window.i18n('changeNickname')} title={window.i18n('changeNickname')}
onClose={onClickClose} onClose={onClickClose}
@ -87,5 +76,3 @@ const SessionNicknameInner = (props: Props) => {
</SessionWrapperModal> </SessionWrapperModal>
); );
}; };
export const SessionNicknameDialog = withTheme(SessionNicknameInner);

@ -10,11 +10,8 @@ import { QRCode } from 'react-qr-svg';
import { mn_decode } from '../../session/crypto/mnemonic'; import { mn_decode } from '../../session/crypto/mnemonic';
import { SessionWrapperModal } from './SessionWrapperModal'; import { SessionWrapperModal } from './SessionWrapperModal';
import { SpacerLG, SpacerSM, SpacerXS } from '../basic/Text'; import { SpacerLG, SpacerSM, SpacerXS } from '../basic/Text';
import autoBind from 'auto-bind';
interface Props { import { recoveryPhraseModal } from '../../state/ducks/modalDialog';
onClose: any;
theme: DefaultTheme;
}
interface State { interface State {
error: string; error: string;
@ -26,7 +23,7 @@ interface State {
passwordValid: boolean; passwordValid: boolean;
} }
class SessionSeedModalInner extends React.Component<Props, State> { class SessionSeedModalInner extends React.Component<{}, State> {
constructor(props: any) { constructor(props: any) {
super(props); super(props);
@ -40,11 +37,7 @@ class SessionSeedModalInner extends React.Component<Props, State> {
passwordValid: false, passwordValid: false,
}; };
this.copyRecoveryPhrase = this.copyRecoveryPhrase.bind(this); autoBind(this);
this.getRecoveryPhrase = this.getRecoveryPhrase.bind(this);
this.confirmPassword = this.confirmPassword.bind(this);
this.checkHasPassword = this.checkHasPassword.bind(this);
this.onEnter = this.onEnter.bind(this);
} }
public componentDidMount() { public componentDidMount() {
@ -57,9 +50,9 @@ class SessionSeedModalInner extends React.Component<Props, State> {
void this.checkHasPassword(); void this.checkHasPassword();
void this.getRecoveryPhrase(); void this.getRecoveryPhrase();
const { onClose } = this.props;
const { hasPassword, passwordValid } = this.state; const { hasPassword, passwordValid } = this.state;
const loading = this.state.loadingPassword || this.state.loadingSeed; const loading = this.state.loadingPassword || this.state.loadingSeed;
const onClose = () => window.inboxStore?.dispatch(recoveryPhraseModal(null));
return ( return (
<> <>
@ -81,7 +74,8 @@ class SessionSeedModalInner extends React.Component<Props, State> {
private renderPasswordView() { private renderPasswordView() {
const error = this.state.error; const error = this.state.error;
const i18n = window.i18n; const i18n = window.i18n;
const { onClose } = this.props;
const onClose = () => window.inboxStore?.dispatch(recoveryPhraseModal(null));
return ( return (
<> <>
@ -206,7 +200,7 @@ class SessionSeedModalInner extends React.Component<Props, State> {
window.clipboard.writeText(recoveryPhrase); window.clipboard.writeText(recoveryPhrase);
ToastUtils.pushCopiedToClipBoard(); ToastUtils.pushCopiedToClipBoard();
this.props.onClose(); window.inboxStore?.dispatch(recoveryPhraseModal(null));
} }
private onEnter(event: any) { private onEnter(event: any) {

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { icons, SessionIconSize, SessionIconType } from '../icon'; import { icons, SessionIconSize, SessionIconType } from '../icon';
import styled, { css, DefaultTheme, keyframes } from 'styled-components'; import styled, { css, DefaultTheme, keyframes, useTheme } from 'styled-components';
import _ from 'lodash'; import _ from 'lodash';
export type SessionIconProps = { export type SessionIconProps = {
@ -12,7 +12,7 @@ export type SessionIconProps = {
glowDuration?: number; glowDuration?: number;
borderRadius?: number; borderRadius?: number;
glowStartDelay?: number; glowStartDelay?: number;
theme: DefaultTheme; theme?: DefaultTheme;
}; };
const getIconDimensionFromIconSize = (iconSize: SessionIconSize | number) => { const getIconDimensionFromIconSize = (iconSize: SessionIconSize | number) => {
@ -163,6 +163,8 @@ export const SessionIcon = (props: SessionIconProps) => {
iconSize = iconSize || SessionIconSize.Medium; iconSize = iconSize || SessionIconSize.Medium;
iconRotation = iconRotation || 0; iconRotation = iconRotation || 0;
const themeToUse = theme || useTheme();
const iconDimensions = getIconDimensionFromIconSize(iconSize); const iconDimensions = getIconDimensionFromIconSize(iconSize);
const iconDef = icons[iconType]; const iconDef = icons[iconType];
const ratio = iconDef?.ratio || 1; const ratio = iconDef?.ratio || 1;
@ -182,7 +184,7 @@ export const SessionIcon = (props: SessionIconProps) => {
borderRadius={borderRadius} borderRadius={borderRadius}
iconRotation={iconRotation} iconRotation={iconRotation}
iconColor={iconColor} iconColor={iconColor}
theme={theme} theme={themeToUse}
/> />
); );
}; };

@ -2,13 +2,13 @@ import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { SessionIcon, SessionIconProps } from '../icon'; import { SessionIcon, SessionIconProps } from '../icon';
import { SessionNotificationCount } from '../SessionNotificationCount'; import { SessionNotificationCount } from '../SessionNotificationCount';
import { DefaultTheme } from 'styled-components'; import { DefaultTheme, useTheme } from 'styled-components';
interface SProps extends SessionIconProps { interface SProps extends SessionIconProps {
onClick?: any; onClick?: any;
notificationCount?: number; notificationCount?: number;
isSelected?: boolean; isSelected?: boolean;
theme: DefaultTheme; theme?: DefaultTheme;
} }
export const SessionIconButton = (props: SProps) => { export const SessionIconButton = (props: SProps) => {
@ -28,6 +28,8 @@ export const SessionIconButton = (props: SProps) => {
} }
}; };
const themeToUSe = theme || useTheme();
return ( return (
<div <div
className={classNames('session-icon-button', iconSize, isSelected ? 'no-opacity' : '')} className={classNames('session-icon-button', iconSize, isSelected ? 'no-opacity' : '')}
@ -39,7 +41,7 @@ export const SessionIconButton = (props: SProps) => {
iconSize={iconSize} iconSize={iconSize}
iconColor={iconColor} iconColor={iconColor}
iconRotation={iconRotation} iconRotation={iconRotation}
theme={theme} theme={themeToUSe}
/> />
{Boolean(notificationCount) && <SessionNotificationCount count={notificationCount} />} {Boolean(notificationCount) && <SessionNotificationCount count={notificationCount} />}
</div> </div>

@ -55,12 +55,8 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => {
currentNotificationSetting, currentNotificationSetting,
} = props; } = props;
const [modal, setModal] = useState<any>(null);
return ( return (
<> <>
{modal ? modal : null}
<Menu id={triggerId} animation={animation.fade}> <Menu id={triggerId} animation={animation.fade}>
{getDisappearingMenuItem( {getDisappearingMenuItem(
isPublic, isPublic,
@ -82,20 +78,13 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => {
{getCopyMenuItem(isPublic, isGroup, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)}
{getMarkAllReadMenuItem(conversationId)} {getMarkAllReadMenuItem(conversationId)}
{getChangeNicknameMenuItem(isMe, isGroup, conversationId, setModal)} {getChangeNicknameMenuItem(isMe, isGroup, conversationId)}
{getClearNicknameMenuItem(isMe, hasNickname, isGroup, conversationId)} {getClearNicknameMenuItem(isMe, hasNickname, isGroup, conversationId)}
{getDeleteMessagesMenuItem(isPublic, conversationId)} {getDeleteMessagesMenuItem(isPublic, conversationId)}
{getAddModeratorsMenuItem(isAdmin, isKickedFromGroup, conversationId)} {getAddModeratorsMenuItem(isAdmin, isKickedFromGroup, conversationId)}
{getRemoveModeratorsMenuItem(isAdmin, isKickedFromGroup, conversationId)} {getRemoveModeratorsMenuItem(isAdmin, isKickedFromGroup, conversationId)}
{getUpdateGroupNameMenuItem(isAdmin, isKickedFromGroup, left, conversationId)} {getUpdateGroupNameMenuItem(isAdmin, isKickedFromGroup, left, conversationId)}
{getLeaveGroupMenuItem( {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, conversationId)}
isKickedFromGroup,
left,
isGroup,
isPublic,
conversationId,
setModal
)}
{/* TODO: add delete group */} {/* TODO: add delete group */}
{getInviteContactMenuItem(isGroup, isPublic, conversationId)} {getInviteContactMenuItem(isGroup, isPublic, conversationId)}
{getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, conversationId)} {getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, conversationId)}

@ -43,30 +43,19 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI
const isGroup = type === 'group'; const isGroup = type === 'group';
const [modal, setModal] = useState<any>(null);
return ( return (
<> <>
{modal ? modal : null}
<Menu id={triggerId} animation={animation.fade}> <Menu id={triggerId} animation={animation.fade}>
{getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)} {getBlockMenuItem(isMe, type === ConversationTypeEnum.PRIVATE, isBlocked, conversationId)}
{getCopyMenuItem(isPublic, isGroup, conversationId)} {getCopyMenuItem(isPublic, isGroup, conversationId)}
{getMarkAllReadMenuItem(conversationId)} {getMarkAllReadMenuItem(conversationId)}
{getChangeNicknameMenuItem(isMe, isGroup, conversationId, setModal)} {getChangeNicknameMenuItem(isMe, isGroup, conversationId)}
{getClearNicknameMenuItem(isMe, hasNickname, isGroup, conversationId)} {getClearNicknameMenuItem(isMe, hasNickname, isGroup, conversationId)}
{getDeleteMessagesMenuItem(isPublic, conversationId)} {getDeleteMessagesMenuItem(isPublic, conversationId)}
{getInviteContactMenuItem(isGroup, isPublic, conversationId)} {getInviteContactMenuItem(isGroup, isPublic, conversationId)}
{getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, conversationId)} {getDeleteContactMenuItem(isMe, isGroup, isPublic, left, isKickedFromGroup, conversationId)}
{getLeaveGroupMenuItem( {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, conversationId)}
isKickedFromGroup,
left,
isGroup,
isPublic,
conversationId,
setModal
)}
</Menu> </Menu>
</> </>
); );

@ -3,9 +3,12 @@ import React from 'react';
import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader'; import { NotificationForConvoOption, TimerOption } from '../../conversation/ConversationHeader';
import { Item, Submenu } from 'react-contexify'; import { Item, Submenu } from 'react-contexify';
import { ConversationNotificationSettingType } from '../../../models/conversation'; import { ConversationNotificationSettingType } from '../../../models/conversation';
import { SessionNicknameDialog } from '../SessionNicknameDialog';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { updateConfirmModal } from '../../../state/ducks/modalDialog'; import {
adminLeaveClosedGroup,
changeNickNameModal,
updateConfirmModal,
} from '../../../state/ducks/modalDialog';
import { ConversationController } from '../../../session/conversations'; import { ConversationController } from '../../../session/conversations';
import { UserUtils } from '../../../session/utils'; import { UserUtils } from '../../../session/utils';
import { AdminLeaveClosedGroupDialog } from '../../conversation/AdminLeaveClosedGroupDialog'; import { AdminLeaveClosedGroupDialog } from '../../conversation/AdminLeaveClosedGroupDialog';
@ -179,8 +182,7 @@ export function getLeaveGroupMenuItem(
left: boolean | undefined, left: boolean | undefined,
isGroup: boolean | undefined, isGroup: boolean | undefined,
isPublic: boolean | undefined, isPublic: boolean | undefined,
conversationId: string, conversationId: string
setModal: any
): JSX.Element | null { ): JSX.Element | null {
if ( if (
showLeaveGroup(Boolean(isKickedFromGroup), Boolean(left), Boolean(isGroup), Boolean(isPublic)) showLeaveGroup(Boolean(isKickedFromGroup), Boolean(left), Boolean(isGroup), Boolean(isPublic))
@ -218,15 +220,10 @@ export function getLeaveGroupMenuItem(
}) })
); );
} else { } else {
setModal( dispatch(
<AdminLeaveClosedGroupDialog adminLeaveClosedGroup({
groupName={conversation.getName()} conversationId,
onSubmit={conversation.leaveClosedGroup} })
onClose={() => {
setModal(null);
}}
theme={theme}
/>
); );
} }
}; };
@ -429,22 +426,18 @@ export function getClearNicknameMenuItem(
export function getChangeNicknameMenuItem( export function getChangeNicknameMenuItem(
isMe: boolean | undefined, isMe: boolean | undefined,
isGroup: boolean | undefined, isGroup: boolean | undefined,
conversationId?: string, conversationId: string
setModal?: any
): JSX.Element | null { ): JSX.Element | null {
const dispatch = useDispatch();
if (showChangeNickname(Boolean(isMe), Boolean(isGroup))) { if (showChangeNickname(Boolean(isMe), Boolean(isGroup))) {
const clearModal = () => {
setModal(null);
};
const onClickCustom = () => {
setModal(<SessionNicknameDialog onClickClose={clearModal} conversationId={conversationId} />);
};
return ( return (
<> <Item
<Item onClick={onClickCustom}>{window.i18n('changeNickname')}</Item> onClick={() => {
</> dispatch(changeNickNameModal({ conversationId }));
}}
>
{window.i18n('changeNickname')}
</Item>
); );
} }
return null; return null;

@ -17,6 +17,7 @@ import _ from 'lodash';
import { ConversationController } from '../session/conversations'; import { ConversationController } from '../session/conversations';
import { BlockedNumberController } from '../util/blockedNumberController'; import { BlockedNumberController } from '../util/blockedNumberController';
import { import {
changeNickNameModal,
updateAddModeratorsModal, updateAddModeratorsModal,
updateConfirmModal, updateConfirmModal,
updateGroupMembersModal, updateGroupMembersModal,
@ -235,6 +236,10 @@ export async function clearNickNameByConvoId(conversationId: string) {
await conversation.setNickname(''); await conversation.setNickname('');
} }
export function showChangeNickNameByConvoId(conversationId: string) {
window.inboxStore?.dispatch(changeNickNameModal({ conversationId }));
}
export async function deleteMessagesByConvoIdNoConfirmation(conversationId: string) { export async function deleteMessagesByConvoIdNoConfirmation(conversationId: string) {
const conversation = ConversationController.getInstance().get(conversationId); const conversation = ConversationController.getInstance().get(conversationId);
await removeAllMessagesInConversation(conversationId); await removeAllMessagesInConversation(conversationId);

@ -3,10 +3,16 @@ import { SessionConfirmDialogProps } from '../../components/session/SessionConfi
export type ConfirmModalState = SessionConfirmDialogProps | null; export type ConfirmModalState = SessionConfirmDialogProps | null;
export type InviteContactModalState = { conversationId: string } | null; export type InviteContactModalState = { conversationId: string } | null;
export type AddModeratorsModalState = { conversationId: string } | null; export type AddModeratorsModalState = InviteContactModalState;
export type RemoveModeratorsModalState = { conversationId: string } | null; export type RemoveModeratorsModalState = InviteContactModalState;
export type UpdateGroupMembersModalState = { conversationId: string } | null; export type UpdateGroupMembersModalState = InviteContactModalState;
export type UpdateGroupNameModalState = { conversationId: string } | null; export type UpdateGroupNameModalState = InviteContactModalState;
export type ChangeNickNameModalState = InviteContactModalState;
export type AdminLeaveClosedGroupModalState = InviteContactModalState;
export type EditProfileModalState = {} | null;
export type OnionPathModalState = EditProfileModalState;
export type RecoveryPhraseModalState = EditProfileModalState;
export type UserDetailsModalState = { export type UserDetailsModalState = {
conversationId: string; conversationId: string;
authorAvatarPath?: string; authorAvatarPath?: string;
@ -21,6 +27,11 @@ export type ModalState = {
groupNameModal: UpdateGroupNameModalState; groupNameModal: UpdateGroupNameModalState;
groupMembersModal: UpdateGroupMembersModalState; groupMembersModal: UpdateGroupMembersModalState;
userDetailsModal: UserDetailsModalState; userDetailsModal: UserDetailsModalState;
nickNameModal: ChangeNickNameModalState;
editProfileModal: EditProfileModalState;
onionPathModal: OnionPathModalState;
recoveryPhraseModal: RecoveryPhraseModalState;
adminLeaveClosedGroup: AdminLeaveClosedGroupModalState;
}; };
export const initialModalState: ModalState = { export const initialModalState: ModalState = {
@ -31,6 +42,11 @@ export const initialModalState: ModalState = {
groupNameModal: null, groupNameModal: null,
groupMembersModal: null, groupMembersModal: null,
userDetailsModal: null, userDetailsModal: null,
nickNameModal: null,
editProfileModal: null,
onionPathModal: null,
recoveryPhraseModal: null,
adminLeaveClosedGroup: null,
}; };
const ModalSlice = createSlice({ const ModalSlice = createSlice({
@ -58,6 +74,21 @@ const ModalSlice = createSlice({
updateUserDetailsModal(state, action: PayloadAction<UserDetailsModalState | null>) { updateUserDetailsModal(state, action: PayloadAction<UserDetailsModalState | null>) {
return { ...state, userDetailsModal: action.payload }; return { ...state, userDetailsModal: action.payload };
}, },
changeNickNameModal(state, action: PayloadAction<ChangeNickNameModalState | null>) {
return { ...state, nickNameModal: action.payload };
},
editProfileModal(state, action: PayloadAction<EditProfileModalState | null>) {
return { ...state, editProfileModal: action.payload };
},
onionPathModal(state, action: PayloadAction<OnionPathModalState | null>) {
return { ...state, onionPathModal: action.payload };
},
recoveryPhraseModal(state, action: PayloadAction<RecoveryPhraseModalState | null>) {
return { ...state, onionPathModal: action.payload };
},
adminLeaveClosedGroup(state, action: PayloadAction<AdminLeaveClosedGroupModalState | null>) {
return { ...state, adminLeaveClosedGroup: action.payload };
},
}, },
}); });
@ -70,5 +101,10 @@ export const {
updateGroupNameModal, updateGroupNameModal,
updateGroupMembersModal, updateGroupMembersModal,
updateUserDetailsModal, updateUserDetailsModal,
changeNickNameModal,
editProfileModal,
onionPathModal,
recoveryPhraseModal,
adminLeaveClosedGroup,
} = actions; } = actions;
export const modalReducer = reducer; export const modalReducer = reducer;

@ -3,9 +3,14 @@ import { createSelector } from 'reselect';
import { StateType } from '../reducer'; import { StateType } from '../reducer';
import { import {
AddModeratorsModalState, AddModeratorsModalState,
AdminLeaveClosedGroupModalState,
ChangeNickNameModalState,
ConfirmModalState, ConfirmModalState,
EditProfileModalState,
InviteContactModalState, InviteContactModalState,
ModalState, ModalState,
OnionPathModalState,
RecoveryPhraseModalState,
RemoveModeratorsModalState, RemoveModeratorsModalState,
UpdateGroupMembersModalState, UpdateGroupMembersModalState,
UpdateGroupNameModalState, UpdateGroupNameModalState,
@ -50,3 +55,28 @@ export const getUserDetailsModal = createSelector(
getModal, getModal,
(state: ModalState): UserDetailsModalState => state.userDetailsModal (state: ModalState): UserDetailsModalState => state.userDetailsModal
); );
export const getChangeNickNameDialog = createSelector(
getModal,
(state: ModalState): ChangeNickNameModalState => state.nickNameModal
);
export const getEditProfileDialog = createSelector(
getModal,
(state: ModalState): EditProfileModalState => state.editProfileModal
);
export const getOnionPathDialog = createSelector(
getModal,
(state: ModalState): OnionPathModalState => state.onionPathModal
);
export const getRecoveryPhraseDialog = createSelector(
getModal,
(state: ModalState): RecoveryPhraseModalState => state.recoveryPhraseModal
);
export const getAdminLeaveClosedGroupDialog = createSelector(
getModal,
(state: ModalState): AdminLeaveClosedGroupModalState => state.adminLeaveClosedGroup
);

Loading…
Cancel
Save