@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414limitations under the License.
1515*/
1616
17- import React , { useRef , useState } from "react" ;
17+ import React , { useRef , useState , Dispatch , SetStateAction } from "react" ;
1818import { Room } from "matrix-js-sdk/src" ;
1919import { logger } from "matrix-js-sdk/src/logger" ;
2020
@@ -39,18 +39,70 @@ import { useStateCallback } from "../../../hooks/useStateCallback";
3939import Exporter from "../../../utils/exportUtils/Exporter" ;
4040import Spinner from "../elements/Spinner" ;
4141import InfoDialog from "./InfoDialog" ;
42+ import ChatExport from "../../../customisations/ChatExport" ;
43+ import { validateNumberInRange } from "../../../utils/validate" ;
4244
4345interface IProps extends IDialogProps {
4446 room : Room ;
4547}
4648
49+ interface ExportConfig {
50+ exportFormat : ExportFormat ;
51+ exportType : ExportType ;
52+ numberOfMessages : number ;
53+ sizeLimit : number ;
54+ includeAttachments : boolean ;
55+ setExportFormat ?: Dispatch < SetStateAction < ExportFormat > > ;
56+ setExportType ?: Dispatch < SetStateAction < ExportType > > ;
57+ setAttachments ?: Dispatch < SetStateAction < boolean > > ;
58+ setNumberOfMessages ?: Dispatch < SetStateAction < number > > ;
59+ setSizeLimit ?: Dispatch < SetStateAction < number > > ;
60+ }
61+
62+ /**
63+ * Set up form state using "forceRoomExportParameters" or defaults
64+ * Form fields configured in ForceRoomExportParameters are not allowed to be edited
65+ * Only return change handlers for editable values
66+ */
67+ const useExportFormState = ( ) : ExportConfig => {
68+ const config = ChatExport . getForceChatExportParameters ( ) ;
69+
70+ const [ exportFormat , setExportFormat ] = useState ( config . format ?? ExportFormat . Html ) ;
71+ const [ exportType , setExportType ] = useState ( config . range ?? ExportType . Timeline ) ;
72+ const [ includeAttachments , setAttachments ] =
73+ useState ( config . includeAttachments ?? false ) ;
74+ const [ numberOfMessages , setNumberOfMessages ] = useState < number > ( config . numberOfMessages ?? 100 ) ;
75+ const [ sizeLimit , setSizeLimit ] = useState < number | null > ( config . sizeMb ?? 8 ) ;
76+
77+ return {
78+ exportFormat,
79+ exportType,
80+ includeAttachments,
81+ numberOfMessages,
82+ sizeLimit,
83+ setExportFormat : ! config . format ? setExportFormat : undefined ,
84+ setExportType : ! config . range ? setExportType : undefined ,
85+ setNumberOfMessages : ! config . numberOfMessages ? setNumberOfMessages : undefined ,
86+ setSizeLimit : ! config . sizeMb ? setSizeLimit : undefined ,
87+ setAttachments : config . includeAttachments === undefined ? setAttachments : undefined ,
88+ } ;
89+ } ;
90+
4791const ExportDialog : React . FC < IProps > = ( { room, onFinished } ) => {
48- const [ exportFormat , setExportFormat ] = useState ( ExportFormat . Html ) ;
49- const [ exportType , setExportType ] = useState ( ExportType . Timeline ) ;
50- const [ includeAttachments , setAttachments ] = useState ( false ) ;
92+ const {
93+ exportFormat,
94+ exportType,
95+ includeAttachments,
96+ numberOfMessages,
97+ sizeLimit,
98+ setExportFormat,
99+ setExportType,
100+ setNumberOfMessages,
101+ setSizeLimit,
102+ setAttachments,
103+ } = useExportFormState ( ) ;
104+
51105 const [ isExporting , setExporting ] = useState ( false ) ;
52- const [ numberOfMessages , setNumberOfMessages ] = useState < number > ( 100 ) ;
53- const [ sizeLimit , setSizeLimit ] = useState < number | null > ( 8 ) ;
54106 const sizeLimitRef = useRef < Field > ( ) ;
55107 const messageCountRef = useRef < Field > ( ) ;
56108 const [ exportProgressText , setExportProgressText ] = useState ( _t ( "Processing..." ) ) ;
@@ -110,9 +162,10 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
110162 } ;
111163
112164 const onExportClick = async ( ) => {
113- const isValidSize = await sizeLimitRef . current . validate ( {
165+ const isValidSize = ! setSizeLimit || ( await sizeLimitRef . current . validate ( {
114166 focused : false ,
115- } ) ;
167+ } ) ) ;
168+
116169 if ( ! isValidSize ) {
117170 sizeLimitRef . current . validate ( { focused : true } ) ;
118171 return ;
@@ -147,10 +200,8 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
147200 } , {
148201 key : "number" ,
149202 test : ( { value } ) => {
150- const parsedSize = parseFloat ( value ) ;
151- const min = 1 ;
152- const max = 2000 ;
153- return ! ( isNaN ( parsedSize ) || min > parsedSize || parsedSize > max ) ;
203+ const parsedSize = parseInt ( value as string , 10 ) ;
204+ return validateNumberInRange ( 1 , 2000 ) ( parsedSize ) ;
154205 } ,
155206 invalid : ( ) => {
156207 const min = 1 ;
@@ -187,11 +238,8 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
187238 } , {
188239 key : "number" ,
189240 test : ( { value } ) => {
190- const parsedSize = parseFloat ( value ) ;
191- const min = 1 ;
192- const max = 10 ** 8 ;
193- if ( isNaN ( parsedSize ) ) return false ;
194- return ! ( min > parsedSize || parsedSize > max ) ;
241+ const parsedSize = parseInt ( value as string , 10 ) ;
242+ return validateNumberInRange ( 1 , 10 ** 8 ) ( parsedSize ) ;
195243 } ,
196244 invalid : ( ) => {
197245 const min = 1 ;
@@ -236,7 +284,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
236284 } ) ;
237285
238286 let messageCount = null ;
239- if ( exportType === ExportType . LastNMessages ) {
287+ if ( exportType === ExportType . LastNMessages && setNumberOfMessages ) {
240288 messageCount = (
241289 < Field
242290 id = "message-count"
@@ -319,61 +367,74 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
319367 ) }
320368 </ p > : null }
321369
322- < span className = "mx_ExportDialog_subheading" >
323- { _t ( "Format" ) }
324- </ span >
325-
326370 < div className = "mx_ExportDialog_options" >
327- < StyledRadioGroup
328- name = "exportFormat"
329- value = { exportFormat }
330- onChange = { ( key ) => setExportFormat ( ExportFormat [ key ] ) }
331- definitions = { exportFormatOptions }
332- />
371+ { ! ! setExportFormat && < >
372+ < span className = "mx_ExportDialog_subheading" >
373+ { _t ( "Format" ) }
374+ </ span >
333375
334- < span className = "mx_ExportDialog_subheading" >
335- { _t ( "Messages" ) }
336- </ span >
337-
338- < Field
339- id = "export-type"
340- element = "select"
341- value = { exportType }
342- onChange = { ( e ) => {
343- setExportType ( ExportType [ e . target . value ] ) ;
344- } }
345- >
346- { exportTypeOptions }
347- </ Field >
348- { messageCount }
349-
350- < span className = "mx_ExportDialog_subheading" >
351- { _t ( "Size Limit" ) }
352- </ span >
353-
354- < Field
355- id = "size-limit"
356- type = "number"
357- autoComplete = "off"
358- onValidate = { onValidateSize }
359- element = "input"
360- ref = { sizeLimitRef }
361- value = { sizeLimit . toString ( ) }
362- postfixComponent = { sizePostFix }
363- onChange = { ( e ) => setSizeLimit ( parseInt ( e . target . value ) ) }
364- />
376+ < StyledRadioGroup
377+ name = "exportFormat"
378+ value = { exportFormat }
379+ onChange = { ( key ) => setExportFormat ( ExportFormat [ key ] ) }
380+ definitions = { exportFormatOptions }
381+ />
382+ </ > }
383+
384+ {
385+ ! ! setExportType && < >
386+
387+ < span className = "mx_ExportDialog_subheading" >
388+ { _t ( "Messages" ) }
389+ </ span >
390+
391+ < Field
392+ id = "export-type"
393+ element = "select"
394+ value = { exportType }
395+ onChange = { ( e ) => {
396+ setExportType ( ExportType [ e . target . value ] ) ;
397+ } }
398+ >
399+ { exportTypeOptions }
400+ </ Field >
401+ { messageCount }
402+ </ >
403+ }
404+
405+ { setSizeLimit && < >
406+ < span className = "mx_ExportDialog_subheading" >
407+ { _t ( "Size Limit" ) }
408+ </ span >
409+
410+ < Field
411+ id = "size-limit"
412+ type = "number"
413+ autoComplete = "off"
414+ onValidate = { onValidateSize }
415+ element = "input"
416+ ref = { sizeLimitRef }
417+ value = { sizeLimit . toString ( ) }
418+ postfixComponent = { sizePostFix }
419+ onChange = { ( e ) => setSizeLimit ( parseInt ( e . target . value ) ) }
420+ />
421+ </ > }
422+
423+ { setAttachments && < >
424+ < StyledCheckbox
425+ className = "mx_ExportDialog_attachments-checkbox"
426+ id = "include-attachments"
427+ checked = { includeAttachments }
428+ onChange = { ( e ) =>
429+ setAttachments (
430+ ( e . target as HTMLInputElement ) . checked ,
431+ )
432+ }
433+ >
434+ { _t ( "Include Attachments" ) }
435+ </ StyledCheckbox >
436+ </ > }
365437
366- < StyledCheckbox
367- id = "include-attachments"
368- checked = { includeAttachments }
369- onChange = { ( e ) =>
370- setAttachments (
371- ( e . target as HTMLInputElement ) . checked ,
372- )
373- }
374- >
375- { _t ( "Include Attachments" ) }
376- </ StyledCheckbox >
377438 </ div >
378439 { isExporting ? (
379440 < div data-test-id = 'export-progress' className = "mx_ExportDialog_progress" >
0 commit comments