diff --git a/ts/components/session/ActionsPanel.tsx b/ts/components/session/ActionsPanel.tsx index a28d95a08..3f9c856e8 100644 --- a/ts/components/session/ActionsPanel.tsx +++ b/ts/components/session/ActionsPanel.tsx @@ -80,10 +80,10 @@ const Section = (props: { // window.inboxStore?.dispatch(updateConfirmModal({ title: "title test" })); - dispatch(updateConfirmModal({ title: "title test" })); + // dispatch(updateConfirmModal({ title: "title test" })); // setModal( setModal(null)}>); - // setModal(); + setModal(); } else if (type === SectionType.Moon) { const themeFromSettings = window.Events.getThemeSetting(); const updatedTheme = themeFromSettings === 'dark' ? 'light' : 'dark'; @@ -288,12 +288,12 @@ export const ActionsPanel = () => { return ( <> - {/* {modal ? modal : null} */} + {modal ? modal : null} {/* { confirmModalState && confirmModalState.title ?
{confirmModalState.title}
: null} */} { confirmModalState ? : null}
diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index 95205c096..7f1f1f5f0 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -1,6 +1,8 @@ // tslint:disable: no-backbone-get-set-outside-model import React from 'react'; +import { useDispatch } from "react-redux"; +import { updateConfirmModal } from '../../../state/ducks/modalDialog'; import classNames from 'classnames'; @@ -12,7 +14,7 @@ import { AttachmentUtil, GoogleChrome } from '../../../util'; import { ConversationHeaderWithDetails } from '../../conversation/ConversationHeader'; import { SessionRightPanelWithDetails } from './SessionRightPanel'; import { SessionTheme } from '../../../state/ducks/SessionTheme'; -import { DefaultTheme } from 'styled-components'; +import { DefaultTheme, useTheme } from 'styled-components'; import { SessionMessagesList } from './SessionMessagesList'; import { LightboxGallery, MediaItemType } from '../../LightboxGallery'; import { Message } from '../../conversation/media-gallery/types/Message'; @@ -32,6 +34,8 @@ import { getDecryptedMediaUrl } from '../../../session/crypto/DecryptedAttachmen import { deleteOpenGroupMessages } from '../../../interactions/conversation'; import { ConversationTypeEnum } from '../../../models/conversation'; + + interface State { // Message sending progress messageProgressVisible: boolean; diff --git a/ts/components/session/menu/ConversationHeaderMenu.tsx b/ts/components/session/menu/ConversationHeaderMenu.tsx index 84c80f045..6202d50c2 100644 --- a/ts/components/session/menu/ConversationHeaderMenu.tsx +++ b/ts/components/session/menu/ConversationHeaderMenu.tsx @@ -104,11 +104,11 @@ export const ConversationHeaderMenu = (props: PropsConversationHeaderMenu) => { {getMarkAllReadMenuItem(onMarkAllRead, window.i18n)} {getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup, window.i18n, id, setModal)} {getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup, window.i18n)} - {getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n)} + {getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n, id)} {getAddModeratorsMenuItem(isAdmin, isKickedFromGroup, onAddModerators, window.i18n)} {getRemoveModeratorsMenuItem(isAdmin, isKickedFromGroup, onRemoveModerators, window.i18n)} {getUpdateGroupNameMenuItem(isAdmin, isKickedFromGroup, left, onUpdateGroupName, window.i18n)} - {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n)} + {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n, id)} {/* TODO: add delete group */} {getInviteContactMenuItem(isGroup, isPublic, onInviteContacts, window.i18n)} {getDeleteContactMenuItem( diff --git a/ts/components/session/menu/ConversationListItemContextMenu.tsx b/ts/components/session/menu/ConversationListItemContextMenu.tsx index e5db0080b..966ac86c1 100644 --- a/ts/components/session/menu/ConversationListItemContextMenu.tsx +++ b/ts/components/session/menu/ConversationListItemContextMenu.tsx @@ -82,7 +82,7 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI {getChangeNicknameMenuItem(isMe, onChangeNickname, isGroup, window.i18n, id, setModal)} {getClearNicknameMenuItem(isMe, hasNickname, onClearNickname, isGroup, window.i18n)} - {getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n)} + {getDeleteMessagesMenuItem(isPublic, onDeleteMessages, window.i18n, id)} {getInviteContactMenuItem(isGroup, isPublic, onInviteContacts, window.i18n)} {getDeleteContactMenuItem( isMe, @@ -93,7 +93,7 @@ export const ConversationListItemContextMenu = (props: PropsContextConversationI onDeleteContact, window.i18n )} - {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n)} + {getLeaveGroupMenuItem(isKickedFromGroup, left, isGroup, isPublic, onLeaveGroup, window.i18n, id)} ); diff --git a/ts/components/session/menu/Menu.tsx b/ts/components/session/menu/Menu.tsx index fab18049b..d93d063aa 100644 --- a/ts/components/session/menu/Menu.tsx +++ b/ts/components/session/menu/Menu.tsx @@ -3,6 +3,11 @@ import { LocalizerType } from '../../../types/Util'; import { TimerOption } from '../../conversation/ConversationHeader'; import { Item, Submenu } from 'react-contexify'; import { SessionNicknameDialog } from '../SessionNicknameDialog'; +import { useDispatch } from 'react-redux'; +import { updateConfirmModal } from '../../../state/ducks/modalDialog'; +import { ConversationController } from '../../../session/conversations'; +import { useTheme } from 'styled-components'; +import { UserUtils } from '../../../session/utils'; function showTimerOptions( isPublic: boolean, @@ -120,12 +125,46 @@ export function getLeaveGroupMenuItem( isGroup: boolean | undefined, isPublic: boolean | undefined, action: any, - i18n: LocalizerType + i18n: LocalizerType, + id: string ): JSX.Element | null { if ( showLeaveGroup(Boolean(isKickedFromGroup), Boolean(left), Boolean(isGroup), Boolean(isPublic)) ) { - return {i18n('leaveGroup')}; + const dispatch = useDispatch(); + const conversation = ConversationController.getInstance().get(id); + + const onClickClose = () => { + dispatch(updateConfirmModal(null)); + } + + const openConfirmationModal = () => { + if (!conversation.isGroup()) { + throw new Error('showLeaveGroupDialog() called with a non group convo.'); + } + + const title = window.i18n('leaveGroup'); + const message = window.i18n('leaveGroupConfirmation'); + const ourPK = UserUtils.getOurPubKeyStrFromCache(); + const isAdmin = (conversation.get('groupAdmins') || []).includes(ourPK); + const isClosedGroup = conversation.get('is_medium_group') || false; + + // if this is not a closed group, or we are not admin, we can just show a confirmation dialog + if (!isClosedGroup || (isClosedGroup && !isAdmin)) { + dispatch(updateConfirmModal({ + title, + message, + onClickOk: () => { + conversation.leaveClosedGroup(); + onClickClose(); + }, + onClickClose + })); + } + + } + + return {i18n('leaveGroup')}; } return null; } @@ -305,10 +344,33 @@ export function getChangeNicknameMenuItem( export function getDeleteMessagesMenuItem( isPublic: boolean | undefined, action: any, - i18n: LocalizerType + i18n: LocalizerType, + id: string ): JSX.Element | null { if (showDeleteMessages(Boolean(isPublic))) { - return {i18n('deleteMessages')}; + + const dispatch = useDispatch(); + const conversation = ConversationController.getInstance().get(id); + + const onClickClose = () => { + dispatch(updateConfirmModal(null)); + } + + const onClickOk = () => { + conversation.destroyMessages(); + onClickClose(); + } + + const openConfirmationModal = () => { + dispatch(updateConfirmModal({ + title: window.i18n('deleteMessages'), + message: window.i18n('deleteConversationConfirmation'), + onClickOk, + onClickClose, + })) + } + + return {i18n('deleteMessages')}; } return null; } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index c8c740efd..d85fed1bd 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1351,7 +1351,7 @@ export class ConversationModel extends Backbone.Model { }; } - window.confirmationDialog(params); + // window.confirmationDialog(params); } public async destroyMessages() { diff --git a/ts/receiver/closedGroups.tsx b/ts/receiver/closedGroups.tsx index 9d87b9a1c..2d7a0fe96 100644 --- a/ts/receiver/closedGroups.tsx +++ b/ts/receiver/closedGroups.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { SignalService } from '../protobuf'; import { removeFromCache } from './cache'; import { EnvelopePlus } from './types'; @@ -36,7 +35,10 @@ import { queueAllCachedFromSource } from './receiver'; import { actions as conversationActions } from '../state/ducks/conversations'; import { SwarmPolling } from '../session/snode_api/swarmPolling'; import { MessageModel } from '../models/message'; -import { SessionConfirm } from '../components/session/SessionConfirm'; + +import { useSelector, useDispatch } from "react-redux"; +import { updateConfirmModal } from "../state/ducks/modalDialog"; + export const distributingClosedGroupEncryptionKeyPairs = new Map(); @@ -943,6 +945,8 @@ async function sendToGroupMembers( const inviteResults = await Promise.all(promises); const allInvitesSent = _.every(inviteResults, Boolean); + // const dispatch = useDispatch(); + if (allInvitesSent) { if (isRetry) { const invitesTitle = @@ -956,6 +960,8 @@ async function sendToGroupMembers( title: invitesTitle, message: window.i18n('closedGroupInviteSuccessMessage'), }); + + // dispatch(updateConfirmModal({ title: "invitesTitle" })) } return allInvitesSent; } else { diff --git a/ts/state/ducks/modalDialog.tsx b/ts/state/ducks/modalDialog.tsx index 14a0a1a81..5aa7ef7b7 100644 --- a/ts/state/ducks/modalDialog.tsx +++ b/ts/state/ducks/modalDialog.tsx @@ -3,53 +3,6 @@ import { DefaultTheme } from 'styled-components'; import { SessionIconSize, SessionIconType } from '../../components/session/icon'; import { SessionButtonColor } from '../../components/session/SessionButton'; - -// import { OpenGroupV2InfoJoinable } from '../../opengroup/opengroupV2/ApiUtil'; - -// export type DefaultRoomsState = Array; - -// const initialState: DefaultRoomsState = []; - -// /** -// * Payload to dispatch to update the base64 data of a default room -// */ -// export type Base64Update = { -// base64Data: string; -// roomId: string; -// }; - -// /** -// * This slice is the one holding the default joinable rooms fetched once in a while from the default opengroup v2 server. -// */ -// const defaultRoomsSlice = createSlice({ -// name: 'defaultRooms', -// initialState, -// reducers: { -// updateDefaultRooms(state, action) { -// window.log.warn('updating default rooms', action.payload); -// return action.payload as DefaultRoomsState; -// }, -// updateDefaultBase64RoomData(state, action: PayloadAction) { -// const payload = action.payload; -// const newState = state.map(room => { -// if (room.id === payload.roomId) { -// return { -// ...room, -// base64Data: payload.base64Data, -// }; -// } -// return room; -// }); -// return newState; -// }, -// }, -// }); - -// const { actions, reducer } = defaultRoomsSlice; -// export const { updateDefaultRooms, updateDefaultBase64RoomData } = actions; -// export const defaultRoomReducer = reducer; - - export type ConfirmModalState = { message?: string; messageSub?: string;