@@ -76,6 +76,12 @@ import { strictAssert } from '../util/assert.std.js';
7676import { ConfirmationDialog } from './ConfirmationDialog.dom.js' ;
7777import type { EmojiSkinTone } from './fun/data/emojis.std.js' ;
7878import { FunPickerButton } from './fun/FunButton.dom.js' ;
79+ import { AxoDropdownMenu } from '../axo/AxoDropdownMenu.dom.js' ;
80+ import { AxoSymbol } from '../axo/AxoSymbol.dom.js' ;
81+ import { AxoButton } from '../axo/AxoButton.dom.js' ;
82+ import { tw } from '../axo/tw.dom.js' ;
83+ import { isPollSendEnabled , type PollCreateType } from '../types/Polls.dom.js' ;
84+ import { PollCreateModal } from './PollCreateModal.dom.js' ;
7985
8086export type OwnProps = Readonly < {
8187 acceptedMessageRequest : boolean | null ;
@@ -160,6 +166,7 @@ export type OwnProps = Readonly<{
160166 voiceNoteAttachment ?: InMemoryAttachmentDraftType ;
161167 }
162168 ) : unknown ;
169+ sendPoll ( conversationId : string , poll : PollCreateType ) : unknown ;
163170 quotedMessageId : string | null ;
164171 quotedMessageProps : null | ReadonlyDeep <
165172 Omit <
@@ -244,6 +251,7 @@ export const CompositionArea = memo(function CompositionArea({
244251 removeAttachment,
245252 sendEditedMessage,
246253 sendMultiMediaMessage,
254+ sendPoll,
247255 setComposerFocus,
248256 setMessageToEdit,
249257 setQuoteByMessageId,
@@ -332,8 +340,10 @@ export const CompositionArea = memo(function CompositionArea({
332340 const [ attachmentToEdit , setAttachmentToEdit ] = useState <
333341 AttachmentDraftType | undefined
334342 > ( ) ;
343+ const [ isPollModalOpen , setIsPollModalOpen ] = useState ( false ) ;
335344 const inputApiRef = useRef < InputApi | undefined > ( ) ;
336345 const fileInputRef = useRef < null | HTMLInputElement > ( null ) ;
346+ const photoVideoInputRef = useRef < null | HTMLInputElement > ( null ) ;
337347
338348 const handleForceSend = useCallback ( ( ) => {
339349 setLarge ( false ) ;
@@ -407,8 +417,9 @@ export const CompositionArea = memo(function CompositionArea({
407417 ]
408418 ) ;
409419
410- const launchAttachmentPicker = useCallback ( ( ) => {
411- const fileInput = fileInputRef . current ;
420+ const launchAttachmentPicker = useCallback ( ( type ?: 'media' | 'file' ) => {
421+ const inputRef = type === 'media' ? photoVideoInputRef : fileInputRef ;
422+ const fileInput = inputRef . current ;
412423 if ( fileInput ) {
413424 // Setting the value to empty so that onChange always fires in case
414425 // you add multiple photos.
@@ -417,6 +428,32 @@ export const CompositionArea = memo(function CompositionArea({
417428 }
418429 } , [ ] ) ;
419430
431+ const launchMediaPicker = useCallback (
432+ ( ) => launchAttachmentPicker ( 'media' ) ,
433+ [ launchAttachmentPicker ]
434+ ) ;
435+
436+ const launchFilePicker = useCallback (
437+ ( ) => launchAttachmentPicker ( 'file' ) ,
438+ [ launchAttachmentPicker ]
439+ ) ;
440+
441+ const handleOpenPollModal = useCallback ( ( ) => {
442+ setIsPollModalOpen ( true ) ;
443+ } , [ ] ) ;
444+
445+ const handleClosePollModal = useCallback ( ( ) => {
446+ setIsPollModalOpen ( false ) ;
447+ } , [ ] ) ;
448+
449+ const handleSendPoll = useCallback (
450+ ( poll : PollCreateType ) => {
451+ sendPoll ( conversationId , poll ) ;
452+ handleClosePollModal ( ) ;
453+ } ,
454+ [ conversationId , sendPoll , handleClosePollModal ]
455+ ) ;
456+
420457 function maybeEditAttachment ( attachment : AttachmentDraftType ) {
421458 if ( ! isImageTypeSupported ( attachment . contentType ) ) {
422459 return ;
@@ -444,7 +481,7 @@ export const CompositionArea = memo(function CompositionArea({
444481
445482 const [ hasFocus , setHasFocus ] = useState ( false ) ;
446483
447- const attachFileShortcut = useAttachFileShortcut ( launchAttachmentPicker ) ;
484+ const attachFileShortcut = useAttachFileShortcut ( launchFilePicker ) ;
448485 const editLastMessageSent = useEditLastMessageSent ( maybeEditMessage ) ;
449486 useKeyboardShortcutsConditionally (
450487 hasFocus ,
@@ -708,17 +745,56 @@ export const CompositionArea = memo(function CompositionArea({
708745 ) : null ;
709746
710747 const isRecording = recordingState === RecordingState . Recording ;
711- const attButton =
712- draftEditMessage || linkPreviewResult || isRecording ? undefined : (
748+
749+ let attButton ;
750+ if ( draftEditMessage || linkPreviewResult || isRecording ) {
751+ attButton = undefined ;
752+ } else if ( isPollSendEnabled ( ) ) {
753+ attButton = (
754+ < div className = "CompositionArea__button-cell" >
755+ < AxoDropdownMenu . Root >
756+ < AxoDropdownMenu . Trigger >
757+ < div className = { tw ( 'flex h-8 items-center' ) } >
758+ < AxoButton . Root
759+ variant = "borderless-secondary"
760+ size = "small"
761+ aria-label = { i18n ( 'icu:CompositionArea--attach-plus' ) }
762+ >
763+ < AxoSymbol . Icon label = { null } symbol = "plus" size = { 20 } />
764+ </ AxoButton . Root >
765+ </ div >
766+ </ AxoDropdownMenu . Trigger >
767+ < AxoDropdownMenu . Content >
768+ < AxoDropdownMenu . Item symbol = "photo" onSelect = { launchMediaPicker } >
769+ { i18n ( 'icu:CompositionArea__AttachMenu__PhotosAndVideos' ) }
770+ </ AxoDropdownMenu . Item >
771+ < AxoDropdownMenu . Item symbol = "file" onSelect = { launchFilePicker } >
772+ { i18n ( 'icu:CompositionArea__AttachMenu__File' ) }
773+ </ AxoDropdownMenu . Item >
774+ { conversationType === 'group' && (
775+ < AxoDropdownMenu . Item
776+ symbol = "poll"
777+ onSelect = { handleOpenPollModal }
778+ >
779+ { i18n ( 'icu:CompositionArea__AttachMenu__Poll' ) }
780+ </ AxoDropdownMenu . Item >
781+ ) }
782+ </ AxoDropdownMenu . Content >
783+ </ AxoDropdownMenu . Root >
784+ </ div >
785+ ) ;
786+ } else {
787+ attButton = (
713788 < div className = "CompositionArea__button-cell" >
714789 < button
715790 type = "button"
716791 className = "CompositionArea__attach-file"
717- onClick = { launchAttachmentPicker }
792+ onClick = { launchFilePicker }
718793 aria-label = { i18n ( 'icu:CompositionArea--attach-file' ) }
719794 />
720795 </ div >
721796 ) ;
797+ }
722798
723799 const sendButtonFragment = ! draftEditMessage ? (
724800 < >
@@ -1049,7 +1125,7 @@ export const CompositionArea = memo(function CompositionArea({
10491125 attachments = { draftAttachments }
10501126 canEditImages
10511127 i18n = { i18n }
1052- onAddAttachment = { launchAttachmentPicker }
1128+ onAddAttachment = { launchFilePicker }
10531129 onClickAttachment = { maybeEditAttachment }
10541130 onClose = { ( ) => onClearAttachments ( conversationId ) }
10551131 onCloseAttachment = { attachment => {
@@ -1133,6 +1209,22 @@ export const CompositionArea = memo(function CompositionArea({
11331209 processAttachments = { processAttachments }
11341210 ref = { fileInputRef }
11351211 />
1212+ < CompositionUpload
1213+ conversationId = { conversationId }
1214+ draftAttachments = { draftAttachments }
1215+ i18n = { i18n }
1216+ processAttachments = { processAttachments }
1217+ ref = { photoVideoInputRef }
1218+ acceptMediaOnly
1219+ testId = "attachfile-input-media"
1220+ />
1221+ { isPollModalOpen && (
1222+ < PollCreateModal
1223+ i18n = { i18n }
1224+ onClose = { handleClosePollModal }
1225+ onSendPoll = { handleSendPoll }
1226+ />
1227+ ) }
11361228 </ div >
11371229 ) ;
11381230} ) ;
0 commit comments