11import React , { useContext , useState , useRef , useEffect } from 'react' ;
22import { css } from '@emotion/react' ;
3- import { Box , Icon , Button , Input , Modal } from '@embeddedchat/ui-elements' ;
3+ import {
4+ Box ,
5+ Icon ,
6+ Button ,
7+ Input ,
8+ Modal ,
9+ useTheme ,
10+ } from '@embeddedchat/ui-elements' ;
411import useAttachmentWindowStore from '../../store/attachmentwindow' ;
512import CheckPreviewType from './CheckPreviewType' ;
613import RCContext from '../../context/RCInstance' ;
714import { useMessageStore , useMemberStore } from '../../store' ;
15+ import useSettingsStore from '../../store/settingsStore' ;
816import getAttachmentPreviewStyles from './AttachmentPreview.styles' ;
917import { parseEmoji } from '../../lib/emoji' ;
1018import MembersList from '../Mentions/MembersList' ;
@@ -13,29 +21,30 @@ import useSearchMentionUser from '../../hooks/useSearchMentionUser';
1321
1422const AttachmentPreview = ( ) => {
1523 const { RCInstance, ECOptions } = useContext ( RCContext ) ;
24+ const { theme } = useTheme ( ) ;
1625 const styles = getAttachmentPreviewStyles ( ) ;
1726
1827 const toggle = useAttachmentWindowStore ( ( state ) => state . toggle ) ;
1928 const data = useAttachmentWindowStore ( ( state ) => state . data ) ;
2029 const setData = useAttachmentWindowStore ( ( state ) => state . setData ) ;
30+
2131 const [ isPending , setIsPending ] = useState ( false ) ;
2232 const messageRef = useRef ( null ) ;
2333 const [ showMembersList , setShowMembersList ] = useState ( false ) ;
2434 const [ filteredMembers , setFilteredMembers ] = useState ( [ ] ) ;
2535 const [ mentionIndex , setMentionIndex ] = useState ( - 1 ) ;
2636 const [ startReadMentionUser , setStartReadMentionUser ] = useState ( false ) ;
27- const [ keyPressed , setKeyPressed ] = useState ( null ) ;
2837
29- const [ fileName , setFileName ] = useState ( data ?. name ) ;
38+ const [ fileName , setFileName ] = useState ( data ?. name ?? '' ) ;
39+ useEffect ( ( ) => setFileName ( data ?. name ?? '' ) , [ data ?. name ] ) ;
3040
31- const threadId = useMessageStore ( ( state ) => state . threadMainMessage ?. _id ) ;
32- const handleFileName = ( e ) => {
33- setFileName ( e . target . value ) ;
34- } ;
41+ const [ description , setDescription ] = useState ( '' ) ;
42+ const charCount = description . length ;
43+ const msgMaxLength = useSettingsStore ( ( s ) => s ?. messageLimit ) ;
44+ const isOverLimit = msgMaxLength && charCount > msgMaxLength ;
3545
36- const { members } = useMemberStore ( ( state ) => ( {
37- members : state . members ,
38- } ) ) ;
46+ const threadId = useMessageStore ( ( state ) => state . threadMainMessage ?. _id ) ;
47+ const { members } = useMemberStore ( ( state ) => ( { members : state . members } ) ) ;
3948
4049 const searchMentionUser = useSearchMentionUser (
4150 members ,
@@ -46,47 +55,44 @@ const AttachmentPreview = () => {
4655 setShowMembersList
4756 ) ;
4857
58+ const handleFileName = ( e ) => setFileName ( e . target . value ) ;
59+
4960 const handleFileDescription = ( e ) => {
50- const description = e . target . value ;
51- messageRef . current . value = parseEmoji ( description ) ;
52- searchMentionUser ( description ) ;
61+ const raw = e . target . value || '' ;
62+ setDescription ( raw ) ;
63+
64+ if ( messageRef . current && typeof messageRef . current . value !== 'undefined' ) {
65+ messageRef . current . value = raw ;
66+ }
67+
68+ searchMentionUser ( raw ) ;
5369 } ;
5470
5571 const submit = async ( ) => {
72+ if ( isPending ) return ;
73+ if ( msgMaxLength && description . length > msgMaxLength ) return ;
74+
5675 setIsPending ( true ) ;
57- await RCInstance . sendAttachment (
58- data ,
59- fileName ,
60- messageRef . current . value ,
61- ECOptions ?. enableThreads ? threadId : undefined
62- ) ;
63- toggle ( ) ;
64- setData ( null ) ;
65- if ( isPending ) {
76+ try {
77+ await RCInstance . sendAttachment (
78+ data ,
79+ fileName ,
80+ parseEmoji ( description ) ,
81+ ECOptions ?. enableThreads ? threadId : undefined
82+ ) ;
83+ toggle ( ) ;
84+ setData ( null ) ;
85+ } finally {
6686 setIsPending ( false ) ;
6787 }
6888 } ;
6989
70- useEffect ( ( ) => {
71- const keyHandler = ( e ) => {
72- if ( e . key === 'Enter' ) {
73- e . preventDefault ( ) ;
74- setKeyPressed ( 'Enter' ) ;
75- }
76- } ;
77-
78- document . addEventListener ( 'keydown' , keyHandler ) ;
79- return ( ) => {
80- document . removeEventListener ( 'keydown' , keyHandler ) ;
81- } ;
82- } , [ ] ) ;
83-
84- useEffect ( ( ) => {
85- if ( keyPressed === 'Enter' ) {
90+ const onDescKeyDown = ( e ) => {
91+ if ( e . key === 'Enter' && ! e . shiftKey ) {
92+ e . preventDefault ( ) ;
8693 submit ( ) ;
87- setKeyPressed ( null ) ;
8894 }
89- } , [ keyPressed , submit ] ) ;
95+ } ;
9096
9197 return (
9298 < Modal onClose = { toggle } >
@@ -98,11 +104,12 @@ const AttachmentPreview = () => {
98104 css = { css `
99105 margin-right : 0.5rem ;
100106 ` }
101- /> { ' ' }
107+ />
102108 File Upload
103109 </ Modal . Title >
104110 < Modal . Close onClick = { toggle } />
105111 </ Modal . Header >
112+
106113 < Modal . Content >
107114 < Box css = { styles . modalContent } >
108115 < Box
@@ -113,6 +120,7 @@ const AttachmentPreview = () => {
113120 >
114121 < CheckPreviewType data = { data } />
115122 </ Box >
123+
116124 < Box
117125 css = { css `
118126 margin : 30px ;
@@ -129,9 +137,7 @@ const AttachmentPreview = () => {
129137 File name
130138 </ Box >
131139 < Input
132- onChange = { ( e ) => {
133- handleFileName ( e ) ;
134- } }
140+ onChange = { handleFileName }
135141 value = { fileName }
136142 type = "text"
137143 css = { styles . input }
@@ -150,6 +156,7 @@ const AttachmentPreview = () => {
150156 >
151157 File description
152158 </ Box >
159+
153160 < Box css = { styles . fileDescription } >
154161 < Box css = { styles . mentionListContainer } >
155162 { showMembersList && (
@@ -161,21 +168,73 @@ const AttachmentPreview = () => {
161168 setFilteredMembers = { setFilteredMembers }
162169 setStartReadMentionUser = { setStartReadMentionUser }
163170 setShowMembersList = { setShowMembersList }
164- css = { css `
165- width : auto;
166- ` }
167171 />
168172 ) }
169173 </ Box >
174+
170175 < Input
171- onChange = { ( e ) => {
172- handleFileDescription ( e ) ;
173- } }
176+ onChange = { handleFileDescription }
177+ onKeyDown = { onDescKeyDown }
174178 type = "text"
175- css = { styles . input }
176179 placeholder = "Description"
177180 ref = { messageRef }
181+ value = { description }
182+ css = { css `
183+ ${ styles . input } ;
184+ bor der- color : ${ isOverLimit
185+ ? theme . colors . destructive
186+ : null } ;
187+ color : ${ isOverLimit ? theme . colors . destructive : null } ;
188+ ` }
178189 />
190+
191+ { msgMaxLength && (
192+ < Box
193+ css = { css `
194+ width: 100%;
195+ dis play: flex;
196+ justify- content: space- between;
197+ align- items: center;
198+ margin- to p: 6px;
199+ gap: 12px;
200+ font- size: 0.875rem;
201+ ` }
202+ >
203+ < Box
204+ css = { css `
205+ color : ${ isOverLimit
206+ ? theme . colors . destructive
207+ : 'transparent' } ;
208+ font- weight: 500;
209+ text- align: left;
210+ flex: 1 1 auto ;
211+ white-space: nowrap;
212+ overflow: hidden;
213+ text- overflow: ellipsis ;
214+ ` }
215+ aria-hidden = { ! isOverLimit }
216+ role = { isOverLimit ? 'alert' : undefined }
217+ >
218+ { isOverLimit
219+ ? `Cannot upload file, description is over the ${ msgMaxLength } character limit`
220+ : '' }
221+ </ Box >
222+
223+ < Box
224+ css = { css `
225+ color : ${ isOverLimit
226+ ? theme . colors . destructive
227+ : '#6b7280' } ;
228+ min- width: 68px;
229+ text- align: right;
230+ flex: 0 0 auto ;
231+ ` }
232+ aria-hidden = "true"
233+ >
234+ ({ charCount } /{ msgMaxLength } )
235+ </ Box >
236+ </ Box >
237+ ) }
179238 </ Box >
180239 </ Box >
181240 </ Box >
@@ -190,12 +249,8 @@ const AttachmentPreview = () => {
190249 < Button type = "secondary" onClick = { toggle } >
191250 Cancel
192251 </ Button >
193- < Button
194- disabled = { isPending }
195- onClick = { ( ) => {
196- submit ( ) ;
197- } }
198- >
252+
253+ < Button disabled = { isPending || isOverLimit } onClick = { submit } >
199254 { isPending ? 'Sending...' : 'Send' }
200255 </ Button >
201256 </ Modal . Footer >
0 commit comments