2023-04-21 15:13:40 -07:00
import clsx from 'clsx' ;
import React , { useRef } from 'react' ;
2022-06-20 10:59:51 -07:00
import { defineMessages , FormattedMessage , useIntl } from 'react-intl' ;
2023-04-26 13:53:06 -07:00
import { cancelReplyCompose , setGroupTimelineVisible , uploadCompose } from 'soapbox/actions/compose' ;
2022-06-20 10:59:51 -07:00
import { openModal , closeModal } from 'soapbox/actions/modals' ;
2022-11-15 08:00:49 -08:00
import { checkComposeContent } from 'soapbox/components/modal-root' ;
2023-04-26 13:53:06 -07:00
import { HStack , Modal , Text , Toggle } from 'soapbox/components/ui' ;
import { useAppDispatch , useAppSelector , useCompose , useDraggedFiles } from 'soapbox/hooks' ;
import { useGroup } from 'soapbox/hooks/api' ;
2022-06-20 10:59:51 -07:00
2022-11-16 06:04:40 -08:00
import ComposeForm from '../../../compose/components/compose-form' ;
2022-06-20 10:59:51 -07:00
const messages = defineMessages ( {
close : { id : 'lightbox.close' , defaultMessage : 'Close' } ,
2023-01-16 11:49:44 -08:00
confirm : { id : 'confirmations.cancel.confirm' , defaultMessage : 'Discard' } ,
2022-08-03 15:09:47 -07:00
cancelEditing : { id : 'confirmations.cancel_editing.confirm' , defaultMessage : 'Cancel editing' } ,
2022-06-20 10:59:51 -07:00
} ) ;
interface IComposeModal {
2023-02-15 13:26:27 -08:00
onClose : ( type ? : string ) = > void
2023-04-26 13:07:19 -07:00
composeId? : string
2022-06-20 10:59:51 -07:00
}
2023-04-26 13:07:19 -07:00
const ComposeModal : React.FC < IComposeModal > = ( { onClose , composeId = 'compose-modal' } ) = > {
2022-06-20 10:59:51 -07:00
const intl = useIntl ( ) ;
const dispatch = useAppDispatch ( ) ;
2023-04-21 15:13:40 -07:00
const node = useRef < HTMLDivElement > ( null ) ;
const compose = useCompose ( composeId ) ;
2022-09-10 14:52:06 -07:00
2023-04-26 13:14:54 -07:00
const { id : statusId , privacy , in_reply_to : inReplyTo , quote , group_id : groupId } = compose ! ;
2022-09-10 14:52:06 -07:00
2023-04-21 15:13:40 -07:00
const { isDragging , isDraggedOver } = useDraggedFiles ( node , ( files ) = > {
dispatch ( uploadCompose ( composeId , files , intl ) ) ;
} ) ;
2022-06-20 10:59:51 -07:00
const onClickClose = ( ) = > {
2022-10-01 06:37:54 -07:00
if ( checkComposeContent ( compose ) ) {
2022-06-20 10:59:51 -07:00
dispatch ( openModal ( 'CONFIRM' , {
2022-07-09 09:20:02 -07:00
icon : require ( '@tabler/icons/trash.svg' ) ,
2022-08-03 14:55:14 -07:00
heading : statusId
2022-08-03 15:09:47 -07:00
? < FormattedMessage id = 'confirmations.cancel_editing.heading' defaultMessage = 'Cancel post editing' / >
2023-01-16 11:49:44 -08:00
: < FormattedMessage id = 'confirmations.cancel.heading' defaultMessage = 'Discard post' / > ,
2022-08-03 14:55:14 -07:00
message : statusId
2022-08-03 15:09:47 -07:00
? < FormattedMessage id = 'confirmations.cancel_editing.message' defaultMessage = 'Are you sure you want to cancel editing this post? All changes will be lost.' / >
2023-01-16 11:49:44 -08:00
: < FormattedMessage id = 'confirmations.cancel.message' defaultMessage = 'Are you sure you want to cancel creating this post?' / > ,
2022-08-03 15:09:47 -07:00
confirm : intl.formatMessage ( statusId ? messages.cancelEditing : messages.confirm ) ,
2022-06-20 10:59:51 -07:00
onConfirm : ( ) = > {
dispatch ( closeModal ( 'COMPOSE' ) ) ;
dispatch ( cancelReplyCompose ( ) ) ;
} ,
} ) ) ;
} else {
onClose ( 'COMPOSE' ) ;
}
} ;
const renderTitle = ( ) = > {
if ( statusId ) {
return < FormattedMessage id = 'navigation_bar.compose_edit' defaultMessage = 'Edit post' / > ;
} else if ( privacy === 'direct' ) {
return < FormattedMessage id = 'navigation_bar.compose_direct' defaultMessage = 'Direct message' / > ;
2023-04-26 13:14:54 -07:00
} else if ( inReplyTo && groupId ) {
return < FormattedMessage id = 'navigation_bar.compose_group_reply' defaultMessage = 'Reply to group post' / > ;
} else if ( groupId ) {
return < FormattedMessage id = 'navigation_bar.compose_group' defaultMessage = 'Compose to group' / > ;
2022-06-20 10:59:51 -07:00
} else if ( inReplyTo ) {
return < FormattedMessage id = 'navigation_bar.compose_reply' defaultMessage = 'Reply to post' / > ;
} else if ( quote ) {
return < FormattedMessage id = 'navigation_bar.compose_quote' defaultMessage = 'Quote post' / > ;
} else {
return < FormattedMessage id = 'navigation_bar.compose' defaultMessage = 'Compose new post' / > ;
}
} ;
return (
< Modal
2023-04-21 15:13:40 -07:00
ref = { node }
2022-06-20 10:59:51 -07:00
title = { renderTitle ( ) }
onClose = { onClickClose }
2023-04-21 15:13:40 -07:00
className = { clsx ( {
'border-2 border-primary-600 border-dashed !z-[99]' : isDragging ,
'ring-2 ring-offset-2 ring-primary-600' : isDraggedOver ,
} ) }
2022-06-20 10:59:51 -07:00
>
2023-04-26 13:53:06 -07:00
< ComposeForm
id = { composeId }
extra = { < ComposeFormGroupToggle composeId = { composeId } groupId = { groupId } / > }
/ >
2022-06-20 10:59:51 -07:00
< / Modal >
) ;
} ;
2023-04-26 13:53:06 -07:00
interface IComposeFormGroupToggle {
composeId : string
groupId : string | null
}
const ComposeFormGroupToggle : React.FC < IComposeFormGroupToggle > = ( { composeId , groupId } ) = > {
const dispatch = useAppDispatch ( ) ;
const { group } = useGroup ( groupId || '' , false ) ;
const groupTimelineVisible = useAppSelector ( ( state ) = > ! ! state . compose . get ( composeId ) ? . group_timeline_visible ) ;
const handleToggleChange = ( ) = > {
dispatch ( setGroupTimelineVisible ( composeId , ! groupTimelineVisible ) ) ;
} ;
const labelId = ` group-timeline-visible+ ${ composeId } ` ;
if ( ! group ) return null ;
if ( group . locked ) return null ;
return (
< HStack alignItems = 'center' space = { 4 } >
< label className = 'ml-auto cursor-pointer' htmlFor = { labelId } >
< Text theme = 'muted' >
< FormattedMessage id = 'compose_group.share_to_followers' defaultMessage = 'Share with my followers' / >
< / Text >
< / label >
< Toggle
id = { labelId }
checked = { groupTimelineVisible }
onChange = { handleToggleChange }
size = 'sm'
/ >
< / HStack >
) ;
} ;
2022-06-20 10:59:51 -07:00
export default ComposeModal ;