You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			218 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
		
		
			
		
	
	
			218 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
| 
											6 years ago
										 | import React from 'react'; | ||
| 
											5 years ago
										 | import { ApiV2 } from '../../opengroup/opengroupV2'; | ||
| 
											4 years ago
										 | import { getConversationController } from '../../session/conversations'; | ||
| 
											5 years ago
										 | import { PubKey } from '../../session/types'; | ||
| 
											5 years ago
										 | import { ToastUtils } from '../../session/utils'; | ||
| 
											5 years ago
										 | import { Flex } from '../basic/Flex'; | ||
| 
											5 years ago
										 | import { SessionButton, SessionButtonColor, SessionButtonType } from '../session/SessionButton'; | ||
|  | import { ContactType, SessionMemberListItem } from '../session/SessionMemberListItem'; | ||
| 
											5 years ago
										 | import { SessionSpinner } from '../session/SessionSpinner'; | ||
| 
											5 years ago
										 | import _ from 'lodash'; | ||
| 
											4 years ago
										 | import { SessionWrapperModal } from '../session/SessionWrapperModal'; | ||
| 
											4 years ago
										 | import { updateRemoveModeratorsModal } from '../../state/ducks/modalDialog'; | ||
| 
											6 years ago
										 | interface Props { | ||
| 
											4 years ago
										 |   conversationId: string; | ||
| 
											6 years ago
										 | } | ||
|  | 
 | ||
|  | interface State { | ||
| 
											5 years ago
										 |   modList: Array<ContactType>; | ||
|  |   removingInProgress: boolean; | ||
|  |   firstLoading: boolean; | ||
| 
											6 years ago
										 | } | ||
|  | 
 | ||
|  | export class RemoveModeratorsDialog extends React.Component<Props, State> { | ||
|  |   constructor(props: any) { | ||
|  |     super(props); | ||
|  | 
 | ||
|  |     this.onModClicked = this.onModClicked.bind(this); | ||
|  |     this.closeDialog = this.closeDialog.bind(this); | ||
| 
											5 years ago
										 |     this.removeThem = this.removeThem.bind(this); | ||
| 
											6 years ago
										 | 
 | ||
|  |     this.state = { | ||
| 
											5 years ago
										 |       modList: [], | ||
|  |       removingInProgress: false, | ||
|  |       firstLoading: true, | ||
| 
											6 years ago
										 |     }; | ||
| 
											5 years ago
										 |   } | ||
|  | 
 | ||
| 
											4 years ago
										 |   public componentDidMount() { | ||
| 
											4 years ago
										 |     this.refreshModList(); | ||
| 
											6 years ago
										 |   } | ||
|  | 
 | ||
|  |   public render() { | ||
| 
											5 years ago
										 |     const { i18n } = window; | ||
|  |     const { removingInProgress, firstLoading } = this.state; | ||
| 
											6 years ago
										 |     const hasMods = this.state.modList.length !== 0; | ||
|  | 
 | ||
| 
											4 years ago
										 |     const convo = getConversationController().get(this.props.conversationId); | ||
| 
											4 years ago
										 | 
 | ||
|  |     const chatName = convo.get('name'); | ||
| 
											6 years ago
										 | 
 | ||
| 
											5 years ago
										 |     const title = `${i18n('removeModerators')}: ${chatName}`; | ||
| 
											6 years ago
										 | 
 | ||
| 
											5 years ago
										 |     const renderContent = !firstLoading; | ||
| 
											6 years ago
										 | 
 | ||
| 
											5 years ago
										 |     return ( | ||
| 
											4 years ago
										 |       <SessionWrapperModal title={title} onClose={this.closeDialog}> | ||
| 
											5 years ago
										 |         <Flex container={true} flexDirection="column" alignItems="center"> | ||
|  |           {renderContent && ( | ||
|  |             <> | ||
|  |               <p>Existing moderators:</p> | ||
| 
											5 years ago
										 |               <div className="contact-selection-list">{this.renderMemberList()}</div> | ||
| 
											5 years ago
										 | 
 | ||
|  |               {hasMods ? null : <p>{i18n('noModeratorsToRemove')}</p>} | ||
|  |               <SessionSpinner loading={removingInProgress} /> | ||
|  | 
 | ||
|  |               <div className="session-modal__button-group"> | ||
|  |                 <SessionButton | ||
|  |                   buttonType={SessionButtonType.Brand} | ||
|  |                   buttonColor={SessionButtonColor.Green} | ||
|  |                   onClick={this.removeThem} | ||
|  |                   disabled={removingInProgress} | ||
|  |                   text={i18n('ok')} | ||
|  |                 /> | ||
|  |                 <SessionButton | ||
|  |                   buttonType={SessionButtonType.Brand} | ||
|  |                   buttonColor={SessionButtonColor.Primary} | ||
|  |                   onClick={this.closeDialog} | ||
|  |                   disabled={removingInProgress} | ||
|  |                   text={i18n('cancel')} | ||
|  |                 /> | ||
|  |               </div> | ||
|  |             </> | ||
|  |           )} | ||
|  | 
 | ||
|  |           <SessionSpinner loading={firstLoading} /> | ||
|  |         </Flex> | ||
| 
											4 years ago
										 |       </SessionWrapperModal> | ||
| 
											5 years ago
										 |     ); | ||
| 
											6 years ago
										 |   } | ||
|  | 
 | ||
|  |   private closeDialog() { | ||
| 
											4 years ago
										 |     window.inboxStore?.dispatch(updateRemoveModeratorsModal(null)); | ||
| 
											6 years ago
										 |   } | ||
|  | 
 | ||
| 
											5 years ago
										 |   private renderMemberList() { | ||
|  |     const members = this.state.modList; | ||
|  |     const selectedContacts = members.filter(d => d.checkmarked).map(d => d.id); | ||
|  | 
 | ||
|  |     return members.map((member: ContactType, index: number) => ( | ||
|  |       <SessionMemberListItem | ||
|  |         member={member} | ||
| 
											4 years ago
										 |         key={member.id} | ||
| 
											5 years ago
										 |         index={index} | ||
|  |         isSelected={selectedContacts.some(m => m === member.id)} | ||
|  |         onSelect={(selectedMember: ContactType) => { | ||
|  |           this.onModClicked(selectedMember); | ||
|  |         }} | ||
|  |         onUnselect={(selectedMember: ContactType) => { | ||
|  |           this.onModClicked(selectedMember); | ||
|  |         }} | ||
|  |       /> | ||
|  |     )); | ||
|  |   } | ||
|  | 
 | ||
|  |   private onModClicked(selected: ContactType) { | ||
| 
											5 years ago
										 |     const updatedContacts = this.state.modList.map(member => { | ||
| 
											6 years ago
										 |       if (member.id === selected.id) { | ||
|  |         return { ...member, checkmarked: !member.checkmarked }; | ||
|  |       } else { | ||
|  |         return member; | ||
|  |       } | ||
|  |     }); | ||
|  | 
 | ||
|  |     this.setState(state => { | ||
|  |       return { | ||
|  |         ...state, | ||
| 
											5 years ago
										 |         modList: updatedContacts, | ||
| 
											6 years ago
										 |       }; | ||
|  |     }); | ||
|  |   } | ||
| 
											5 years ago
										 | 
 | ||
| 
											4 years ago
										 |   private refreshModList() { | ||
| 
											5 years ago
										 |     let modPubKeys: Array<string> = []; | ||
| 
											4 years ago
										 |     const convo = getConversationController().get(this.props.conversationId); | ||
| 
											4 years ago
										 | 
 | ||
|  |     modPubKeys = convo.getGroupAdmins() || []; | ||
| 
											4 years ago
										 | 
 | ||
| 
											4 years ago
										 |     const convos = getConversationController().getConversations(); | ||
| 
											5 years ago
										 |     const moderatorsConvos = modPubKeys | ||
|  |       .map( | ||
|  |         pubKey => | ||
|  |           convos.find(c => c.id === pubKey) || { | ||
|  |             id: pubKey, // memberList need a key
 | ||
|  |             authorPhoneNumber: pubKey, | ||
|  |           } | ||
|  |       ) | ||
|  |       .filter(c => !!c); | ||
|  | 
 | ||
|  |     const mods = moderatorsConvos.map((d: any) => { | ||
|  |       let name = ''; | ||
|  |       if (d.getLokiProfile) { | ||
|  |         const lokiProfile = d.getLokiProfile(); | ||
|  |         name = lokiProfile ? lokiProfile.displayName : 'Anonymous'; | ||
|  |       } | ||
|  |       // TODO: should take existing members into account
 | ||
|  |       const existingMember = false; | ||
|  | 
 | ||
|  |       return { | ||
|  |         id: d.id, | ||
|  |         authorPhoneNumber: d.id, | ||
|  |         authorProfileName: name, | ||
|  |         selected: false, | ||
|  |         authorAvatarPath: '', | ||
|  |         authorName: name, | ||
|  |         checkmarked: true, | ||
|  |         existingMember, | ||
|  |       }; | ||
|  |     }); | ||
|  |     this.setState({ | ||
|  |       modList: mods, | ||
|  |       firstLoading: false, | ||
|  |       removingInProgress: false, | ||
|  |     }); | ||
|  |   } | ||
|  | 
 | ||
|  |   private async removeThem() { | ||
| 
											5 years ago
										 |     const removedMods = this.state.modList.filter(d => !d.checkmarked).map(d => d.id); | ||
| 
											5 years ago
										 | 
 | ||
|  |     if (removedMods.length === 0) { | ||
| 
											5 years ago
										 |       window?.log?.info('No moderators removed. Nothing todo'); | ||
| 
											5 years ago
										 |       return; | ||
|  |     } | ||
| 
											5 years ago
										 |     window?.log?.info(`asked to remove moderator: ${removedMods}`); | ||
| 
											5 years ago
										 | 
 | ||
|  |     try { | ||
|  |       this.setState({ | ||
|  |         removingInProgress: true, | ||
|  |       }); | ||
| 
											5 years ago
										 |       let res; | ||
| 
											4 years ago
										 |       const convo = getConversationController().get(this.props.conversationId); | ||
| 
											4 years ago
										 | 
 | ||
|  |       const roomInfos = convo.toOpenGroupV2(); | ||
| 
											4 years ago
										 |       const modsToRemove = _.compact(removedMods.map(m => PubKey.from(m))); | ||
|  |       res = await Promise.all( | ||
|  |         modsToRemove.map(async m => { | ||
|  |           return ApiV2.removeModerator(m, roomInfos); | ||
|  |         }) | ||
|  |       ); | ||
|  |       // all moderators are removed means all promise resolved with bool= true
 | ||
|  |       res = res.every(r => !!r); | ||
|  | 
 | ||
| 
											5 years ago
										 |       if (!res) { | ||
| 
											5 years ago
										 |         window?.log?.warn('failed to remove moderators:', res); | ||
| 
											5 years ago
										 | 
 | ||
| 
											4 years ago
										 |         ToastUtils.pushFailedToRemoveFromModerator(); | ||
| 
											5 years ago
										 |       } else { | ||
| 
											5 years ago
										 |         window?.log?.info(`${removedMods} removed from moderators...`); | ||
| 
											5 years ago
										 |         ToastUtils.pushUserRemovedFromModerators(); | ||
| 
											4 years ago
										 |         this.closeDialog(); | ||
| 
											5 years ago
										 |       } | ||
|  |     } catch (e) { | ||
| 
											4 years ago
										 |       window?.log?.error('Got error while removing moderator:', e); | ||
| 
											5 years ago
										 |     } finally { | ||
| 
											4 years ago
										 |       this.refreshModList(); | ||
| 
											5 years ago
										 |     } | ||
|  |   } | ||
| 
											6 years ago
										 | } |