2023-05-19 05:05:41 +02:00
import _ from 'lodash' ;
2021-07-06 06:01:02 +02:00
import React , { useEffect , useState } from 'react' ;
2021-08-30 09:57:31 +02:00
import { SessionIconButton } from '../icon' ;
2021-12-14 05:15:12 +01:00
// tslint:disable-next-line: no-submodule-imports
import { useDispatch , useSelector } from 'react-redux' ;
2023-05-19 05:05:41 +02:00
import useInterval from 'react-use/lib/useInterval' ;
import styled from 'styled-components' ;
2022-08-08 01:50:48 +02:00
import { Data } from '../../data/data' ;
2021-06-18 06:20:36 +02:00
import {
2021-10-25 08:04:51 +02:00
deleteAllMessagesByConvoIdWithConfirmation ,
2021-06-18 06:20:36 +02:00
setDisappearingMessagesByConvoId ,
showAddModeratorsByConvoId ,
showInviteContactByConvoId ,
showLeaveGroupByConvoId ,
showRemoveModeratorsByConvoId ,
2021-06-21 02:59:37 +02:00
showUpdateGroupMembersByConvoId ,
2021-06-18 06:20:36 +02:00
showUpdateGroupNameByConvoId ,
2021-12-14 05:15:12 +01:00
} from '../../interactions/conversationInteractions' ;
import { Constants } from '../../session' ;
import { closeRightPanel } from '../../state/ducks/conversations' ;
2023-03-24 06:48:50 +01:00
import { isRightPanelShowing } from '../../state/selectors/conversations' ;
import {
useSelectedConversationKey ,
useSelectedDisplayNameInProfile ,
useSelectedIsActive ,
useSelectedIsBlocked ,
useSelectedIsGroup ,
useSelectedIsKickedFromGroup ,
useSelectedIsLeft ,
useSelectedIsPublic ,
useSelectedSubscriberCount ,
useSelectedWeAreAdmin ,
} from '../../state/selectors/selectedConversation' ;
2023-05-19 05:05:41 +02:00
import { getTimerOptions } from '../../state/selectors/timerOptions' ;
import { AttachmentTypeWithPath } from '../../types/Attachment' ;
import { getAbsoluteAttachmentPath } from '../../types/MessageAttachment' ;
import { Avatar , AvatarSize } from '../avatar/Avatar' ;
import { SessionButton , SessionButtonColor , SessionButtonType } from '../basic/SessionButton' ;
import { SessionDropdown } from '../basic/SessionDropdown' ;
import { SpacerLG } from '../basic/Text' ;
import { MediaItemType } from '../lightbox/LightboxGallery' ;
import { MediaGallery } from './media-gallery/MediaGallery' ;
2020-01-12 23:58:14 +01:00
2021-07-06 06:01:02 +02:00
async function getMediaGalleryProps (
2021-07-14 05:48:59 +02:00
conversationId : string
2021-07-06 06:01:02 +02:00
) : Promise < {
documents : Array < MediaItemType > ;
media : Array < MediaItemType > ;
} > {
// We fetch more documents than media as they don’ t require to be loaded
// into memory right away. Revisit this once we have infinite scrolling:
2022-08-08 01:50:48 +02:00
const rawMedia = await Data . getMessagesWithVisualMediaAttachments (
2022-03-29 06:18:26 +02:00
conversationId ,
Constants . CONVERSATION . DEFAULT_MEDIA_FETCH_COUNT
) ;
2022-08-08 01:50:48 +02:00
const rawDocuments = await Data . getMessagesWithFileAttachments (
2022-03-29 06:18:26 +02:00
conversationId ,
Constants . CONVERSATION . DEFAULT_DOCUMENTS_FETCH_COUNT
) ;
2021-07-06 06:01:02 +02:00
const media = _ . flatten (
rawMedia . map ( attributes = > {
const { attachments , source , id , timestamp , serverTimestamp , received_at } = attributes ;
return ( attachments || [ ] )
. filter (
( attachment : AttachmentTypeWithPath ) = >
attachment . thumbnail && ! attachment . pending && ! attachment . error
)
. map ( ( attachment : AttachmentTypeWithPath , index : number ) = > {
const { thumbnail } = attachment ;
const mediaItem : MediaItemType = {
2022-01-09 23:36:17 +01:00
objectURL : getAbsoluteAttachmentPath ( attachment . path ) ,
thumbnailObjectUrl : thumbnail ? getAbsoluteAttachmentPath ( thumbnail . path ) : undefined ,
2021-07-06 06:01:02 +02:00
contentType : attachment.contentType || '' ,
index ,
messageTimestamp : timestamp || serverTimestamp || received_at || 0 ,
messageSender : source ,
messageId : id ,
attachment ,
} ;
return mediaItem ;
} ) ;
} )
) ;
// Unlike visual media, only one non-image attachment is supported
const documents = rawDocuments . map ( attributes = > {
// this is to not fail if the attachment is invalid (could be a Long Attachment type which is not supported)
if ( ! attributes . attachments ? . length ) {
// window?.log?.info(
// 'Got a message with an empty list of attachment. Skipping...'
// );
return null ;
}
const attachment = attributes . attachments [ 0 ] ;
const { source , id , timestamp , serverTimestamp , received_at } = attributes ;
2020-01-13 05:50:18 +01:00
2021-07-06 06:01:02 +02:00
return {
contentType : attachment.contentType ,
index : 0 ,
attachment ,
messageTimestamp : timestamp || serverTimestamp || received_at || 0 ,
messageSender : source ,
messageId : id ,
2020-01-13 05:50:18 +01:00
} ;
2021-07-06 06:01:02 +02:00
} ) ;
return {
media ,
documents : _.compact ( documents ) , // remove null
} ;
}
2020-02-19 01:27:37 +01:00
2021-07-13 09:00:20 +02:00
const HeaderItem = ( ) = > {
2023-03-24 06:48:50 +01:00
const selectedConvoKey = useSelectedConversationKey ( ) ;
2021-07-13 09:00:20 +02:00
const dispatch = useDispatch ( ) ;
2023-03-24 06:48:50 +01:00
const isBlocked = useSelectedIsBlocked ( ) ;
const isKickedFromGroup = useSelectedIsKickedFromGroup ( ) ;
const left = useSelectedIsLeft ( ) ;
const isGroup = useSelectedIsGroup ( ) ;
2021-07-13 09:00:20 +02:00
2023-03-24 06:48:50 +01:00
if ( ! selectedConvoKey ) {
2021-07-13 09:00:20 +02:00
return null ;
}
2021-07-30 02:08:26 +02:00
const showInviteContacts = isGroup && ! isKickedFromGroup && ! isBlocked && ! left ;
2021-07-13 09:00:20 +02:00
return (
< div className = "group-settings-header" >
< SessionIconButton
2021-08-30 09:57:31 +02:00
iconType = "chevron"
2021-11-18 01:36:14 +01:00
iconSize = "medium"
2021-07-13 09:00:20 +02:00
iconRotation = { 270 }
onClick = { ( ) = > {
dispatch ( closeRightPanel ( ) ) ;
} }
2022-08-08 01:50:48 +02:00
style = { { position : 'absolute' } }
2022-05-17 05:22:13 +02:00
dataTestId = "back-button-conversation-options"
2021-07-13 09:00:20 +02:00
/ >
2023-03-24 06:48:50 +01:00
< Avatar size = { AvatarSize . XL } pubkey = { selectedConvoKey } / >
2022-08-19 07:25:26 +02:00
{ showInviteContacts && (
< SessionIconButton
iconType = "addUser"
iconSize = "medium"
onClick = { ( ) = > {
2023-03-24 06:48:50 +01:00
if ( selectedConvoKey ) {
showInviteContactByConvoId ( selectedConvoKey ) ;
2022-08-19 07:25:26 +02:00
}
} }
dataTestId = "add-user-button"
/ >
) }
2021-07-13 09:00:20 +02:00
< / div >
) ;
} ;
2022-09-16 05:39:19 +02:00
const StyledLeaveButton = styled . div `
width : 100 % ;
. session - button {
margin - top : auto ;
width : 100 % ;
2022-09-19 03:07:59 +02:00
min - height : calc ( var ( -- composition - container - height ) + 1 px ) ; // include border in height
2022-09-16 05:39:19 +02:00
flex - shrink : 0 ;
align - items : center ;
2022-09-19 03:07:59 +02:00
border - top : 1px solid var ( -- border - color ) ;
2022-09-16 05:39:19 +02:00
border - radius : 0px ;
& : not ( . disabled ) {
& : hover {
background - color : var ( -- button - solid - background - hover - color ) ;
}
}
}
` ;
2022-10-17 03:28:24 +02:00
const StyledGroupSettingsItem = styled . div `
display : flex ;
align - items : center ;
min - height : 3rem ;
font - size : var ( -- font - size - md ) ;
color : var ( -- right - panel - item - text - color ) ;
background - color : var ( -- right - panel - item - background - color ) ;
border - top : 1px solid var ( -- border - color ) ;
border - bottom : 1px solid var ( -- border - color ) ;
width : - webkit - fill - available ;
padding : 0 var ( -- margins - md ) ;
transition : var ( -- default - duration ) ;
cursor : pointer ;
& : hover {
background - color : var ( -- right - panel - item - background - hover - color ) ;
}
` ;
2023-02-07 06:36:18 +01:00
const StyledName = styled . h4 `
padding - inline : var ( -- margins - md ) ;
font - size : var ( -- font - size - md ) ;
` ;
2021-07-06 06:01:02 +02:00
// tslint:disable: cyclomatic-complexity
// tslint:disable: max-func-body-length
2021-07-14 05:48:59 +02:00
export const SessionRightPanelWithDetails = ( ) = > {
2021-07-06 06:01:02 +02:00
const [ documents , setDocuments ] = useState < Array < MediaItemType > > ( [ ] ) ;
const [ media , setMedia ] = useState < Array < MediaItemType > > ( [ ] ) ;
2021-07-13 09:00:20 +02:00
2023-03-24 06:48:50 +01:00
const selectedConvoKey = useSelectedConversationKey ( ) ;
2021-07-13 09:00:20 +02:00
const isShowing = useSelector ( isRightPanelShowing ) ;
2023-03-24 06:48:50 +01:00
const subscriberCount = useSelectedSubscriberCount ( ) ;
const isActive = useSelectedIsActive ( ) ;
const displayNameInProfile = useSelectedDisplayNameInProfile ( ) ;
const isBlocked = useSelectedIsBlocked ( ) ;
const isKickedFromGroup = useSelectedIsKickedFromGroup ( ) ;
const left = useSelectedIsLeft ( ) ;
const isGroup = useSelectedIsGroup ( ) ;
const isPublic = useSelectedIsPublic ( ) ;
const weAreAdmin = useSelectedWeAreAdmin ( ) ;
2021-07-06 06:01:02 +02:00
useEffect ( ( ) = > {
let isRunning = true ;
2023-03-24 06:48:50 +01:00
if ( isShowing && selectedConvoKey ) {
void getMediaGalleryProps ( selectedConvoKey ) . then ( results = > {
2021-07-14 05:48:59 +02:00
if ( isRunning ) {
if ( ! _ . isEqual ( documents , results . documents ) ) {
2021-07-13 09:00:20 +02:00
setDocuments ( results . documents ) ;
2021-07-14 05:48:59 +02:00
}
if ( ! _ . isEqual ( media , results . media ) ) {
2021-07-13 09:00:20 +02:00
setMedia ( results . media ) ;
}
2021-06-18 06:20:36 +02:00
}
2021-07-14 05:48:59 +02:00
} ) ;
2021-07-06 06:01:02 +02:00
}
2021-01-18 05:29:31 +01:00
2021-07-06 06:01:02 +02:00
return ( ) = > {
isRunning = false ;
return ;
} ;
2023-03-24 06:48:50 +01:00
} , [ isShowing , selectedConvoKey ] ) ;
2021-07-06 06:01:02 +02:00
useInterval ( async ( ) = > {
2023-03-24 06:48:50 +01:00
if ( isShowing && selectedConvoKey ) {
const results = await getMediaGalleryProps ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
if ( results . documents . length !== documents . length || results . media . length !== media . length ) {
setDocuments ( results . documents ) ;
setMedia ( results . media ) ;
}
}
} , 10000 ) ;
2020-01-13 05:50:18 +01:00
2023-03-24 06:48:50 +01:00
if ( ! selectedConvoKey ) {
2021-07-13 09:00:20 +02:00
return null ;
2020-01-13 05:50:18 +01:00
}
2020-09-14 08:06:24 +02:00
2021-07-13 09:00:20 +02:00
const showMemberCount = ! ! ( subscriberCount && subscriberCount > 0 ) ;
2023-03-24 06:48:50 +01:00
const commonNoShow = isKickedFromGroup || left || isBlocked || ! isActive ;
2021-07-06 06:01:02 +02:00
const hasDisappearingMessages = ! isPublic && ! commonNoShow ;
const leaveGroupString = isPublic
? window . i18n ( 'leaveGroup' )
: isKickedFromGroup
? window . i18n ( 'youGotKickedFromGroup' )
: left
? window . i18n ( 'youLeftTheGroup' )
: window . i18n ( 'leaveGroup' ) ;
2021-07-06 06:40:45 +02:00
const timerOptions = useSelector ( getTimerOptions ) . timerOptions ;
2021-07-06 06:01:02 +02:00
const disappearingMessagesOptions = timerOptions . map ( option = > {
return {
content : option.name ,
2021-07-14 05:48:59 +02:00
onClick : ( ) = > {
2023-03-24 06:48:50 +01:00
void setDisappearingMessagesByConvoId ( selectedConvoKey , option . value ) ;
2021-07-06 06:01:02 +02:00
} ,
} ;
} ) ;
2021-07-30 02:08:26 +02:00
const showUpdateGroupNameButton =
isGroup && ( ! isPublic || ( isPublic && weAreAdmin ) ) && ! commonNoShow ;
2021-07-13 09:00:20 +02:00
const showAddRemoveModeratorsButton = weAreAdmin && ! commonNoShow && isPublic ;
2021-07-06 06:01:02 +02:00
const showUpdateGroupMembersButton = ! isPublic && isGroup && ! commonNoShow ;
const deleteConvoAction = isPublic
? ( ) = > {
2023-03-30 05:15:59 +02:00
deleteAllMessagesByConvoIdWithConfirmation ( selectedConvoKey ) ; // TODOLATER this does not delete the public group and showLeaveGroupByConvoId is not only working for closed groups
2021-07-06 06:01:02 +02:00
}
: ( ) = > {
2023-03-24 06:48:50 +01:00
showLeaveGroupByConvoId ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
} ;
return (
< div className = "group-settings" >
2021-07-13 09:00:20 +02:00
< HeaderItem / >
2023-02-07 06:36:18 +01:00
< StyledName data - testid = "right-panel-group-name" > { displayNameInProfile } < / StyledName >
2021-07-06 06:01:02 +02:00
{ showMemberCount && (
< >
< SpacerLG / >
< div role = "button" className = "subtle" >
2021-11-30 04:46:06 +01:00
{ window . i18n ( 'members' , [ ` ${ subscriberCount } ` ] ) }
2021-07-06 06:01:02 +02:00
< / div >
< SpacerLG / >
< / >
) }
{ showUpdateGroupNameButton && (
2022-10-17 03:28:24 +02:00
< StyledGroupSettingsItem
2021-07-06 06:01:02 +02:00
className = "group-settings-item"
role = "button"
onClick = { async ( ) = > {
2023-03-24 06:48:50 +01:00
await showUpdateGroupNameByConvoId ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
} }
>
{ isPublic ? window . i18n ( 'editGroup' ) : window . i18n ( 'editGroupName' ) }
2022-10-17 03:28:24 +02:00
< / StyledGroupSettingsItem >
2021-07-06 06:01:02 +02:00
) }
{ showAddRemoveModeratorsButton && (
< >
2022-10-17 03:28:24 +02:00
< StyledGroupSettingsItem
2021-07-06 06:01:02 +02:00
className = "group-settings-item"
role = "button"
onClick = { ( ) = > {
2023-03-24 06:48:50 +01:00
showAddModeratorsByConvoId ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
} }
>
{ window . i18n ( 'addModerators' ) }
2022-10-17 03:28:24 +02:00
< / StyledGroupSettingsItem >
< StyledGroupSettingsItem
2021-07-06 06:01:02 +02:00
className = "group-settings-item"
role = "button"
onClick = { ( ) = > {
2023-03-24 06:48:50 +01:00
showRemoveModeratorsByConvoId ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
} }
>
{ window . i18n ( 'removeModerators' ) }
2022-10-17 03:28:24 +02:00
< / StyledGroupSettingsItem >
2021-07-06 06:01:02 +02:00
< / >
) }
{ showUpdateGroupMembersButton && (
2022-10-17 03:28:24 +02:00
< StyledGroupSettingsItem
2021-07-06 06:01:02 +02:00
className = "group-settings-item"
role = "button"
onClick = { async ( ) = > {
2023-03-24 06:48:50 +01:00
await showUpdateGroupMembersByConvoId ( selectedConvoKey ) ;
2021-07-06 06:01:02 +02:00
} }
>
{ window . i18n ( 'groupMembers' ) }
2022-10-17 03:28:24 +02:00
< / StyledGroupSettingsItem >
2021-07-06 06:01:02 +02:00
) }
{ hasDisappearingMessages && (
< SessionDropdown
label = { window . i18n ( 'disappearingMessages' ) }
options = { disappearingMessagesOptions }
/ >
) }
2021-07-14 05:48:59 +02:00
< MediaGallery documents = { documents } media = { media } / >
2021-07-06 06:01:02 +02:00
{ isGroup && (
// tslint:disable-next-line: use-simple-attributes
2022-09-16 05:39:19 +02:00
< StyledLeaveButton >
2022-09-16 05:43:49 +02:00
< SessionButton
2022-09-16 05:39:19 +02:00
text = { leaveGroupString }
buttonColor = { SessionButtonColor . Danger }
buttonType = { SessionButtonType . Simple }
disabled = { isKickedFromGroup || left }
onClick = { deleteConvoAction }
/ >
< / StyledLeaveButton >
2021-07-06 06:01:02 +02:00
) }
< / div >
) ;
} ;