1- import { Document , Page , pdf , Text , View } from '@react-pdf/renderer' ;
2- import type { IMessage } from '@rocket.chat/core-typings' ;
1+ import { Document , Image , Page , pdf , StyleSheet , Text , View } from '@react-pdf/renderer' ;
2+ import type { IMessage , MessageAttachmentDefault } from '@rocket.chat/core-typings' ;
33import { escapeHTML } from '@rocket.chat/string-helpers' ;
4- import { useSetting } from '@rocket.chat/ui-contexts' ;
4+ import { useSetting , useToastMessageDispatch } from '@rocket.chat/ui-contexts' ;
55import { useMutation } from '@tanstack/react-query' ;
66import { useTranslation } from 'react-i18next' ;
77
88import { Messages } from '../../../../../app/models/client' ;
99import { MessageTypes } from '../../../../../app/ui-utils/lib/MessageTypes' ;
1010import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime' ;
1111
12+ const leftTab = {
13+ marginLeft : 20 ,
14+ } ;
15+
16+ const pdfStyles = StyleSheet . create ( {
17+ messageHeader : {
18+ display : 'flex' ,
19+ flexDirection : 'row' ,
20+ alignItems : 'flex-end' ,
21+ gap : 10 ,
22+ } ,
23+ username : {
24+ color : '#000' ,
25+ fontSize : 14 ,
26+ } ,
27+ dateTime : {
28+ color : '#aaa' ,
29+ fontSize : 12 ,
30+ } ,
31+ threadMessagesCount : {
32+ color : '#000' ,
33+ fontSize : 14 ,
34+ } ,
35+ threadMessage : {
36+ color : '#555' ,
37+ fontSize : 12 ,
38+ ...leftTab ,
39+ } ,
40+ message : {
41+ color : '#555' ,
42+ fontSize : 14 ,
43+ } ,
44+ } ) ;
45+
1246export const useExportMessagesAsPDFMutation = ( ) => {
1347 const { t } = useTranslation ( ) ;
1448 const chatopsUsername = useSetting ( 'Chatops_Username' ) ;
1549 const formatDateAndTime = useFormatDateAndTime ( ) ;
50+ const dispatchToastMessage = useToastMessageDispatch ( ) ;
1651
1752 return useMutation ( {
1853 mutationFn : async ( messageIds : IMessage [ '_id' ] [ ] ) => {
@@ -48,12 +83,21 @@ export const useExportMessagesAsPDFMutation = () => {
4883 { messages . map ( ( message ) => {
4984 const dateTime = formatDateAndTime ( message . ts ) ;
5085 return (
51- < Text key = { message . _id } style = { { marginBottom : 5 } } >
52- < Text style = { { color : '#555' , fontSize : 14 } } > { message . u . username } </ Text > { ' ' }
53- < Text style = { { color : '#aaa' , fontSize : 12 } } > { dateTime } </ Text >
54- < Text > { '\n' } </ Text >
55- { parseMessage ( message ) }
56- </ Text >
86+ < View key = { message . _id } style = { { marginBottom : 10 } } >
87+ < View style = { pdfStyles . messageHeader } >
88+ < Text style = { { ...( message . tmid ? leftTab : { } ) , ...pdfStyles . username } } > { message . u . username } </ Text >
89+ < Text style = { pdfStyles . dateTime } > { dateTime } </ Text >
90+ { message . tcount && < Text style = { pdfStyles . threadMessagesCount } > { `${ message . tcount } ${ t ( 'thread_messages' ) } ` } </ Text > }
91+ </ View >
92+ < Text style = { message . tmid ? pdfStyles . threadMessage : pdfStyles . message } > { parseMessage ( message ) } </ Text >
93+ { message . attachments ?. map ( ( attachment : MessageAttachmentDefault , index ) => (
94+ < View key = { index } >
95+ { attachment . description && < Text style = { pdfStyles . message } > { attachment . description } </ Text > }
96+ { attachment . image_url && < Image src = { attachment . title_link } style = { attachment . image_dimensions } /> }
97+ < Text style = { pdfStyles . message } > { attachment . title } </ Text >
98+ </ View >
99+ ) ) }
100+ </ View >
57101 ) ;
58102 } ) }
59103 </ View >
@@ -63,22 +107,33 @@ export const useExportMessagesAsPDFMutation = () => {
63107
64108 const instance = pdf ( ) ;
65109
66- const callback = async ( ) => {
67- const link = document . createElement ( 'a' ) ;
68- link . href = URL . createObjectURL ( await instance . toBlob ( ) ) ;
69- link . download = `exportedMessages-${ new Date ( ) . toISOString ( ) } .pdf` ;
70- document . body . appendChild ( link ) ;
71- link . click ( ) ;
72- document . body . removeChild ( link ) ;
73- URL . revokeObjectURL ( link . href ) ;
74- } ;
110+ await new Promise < void > ( ( resolve , reject ) => {
111+ const callback = async ( ) => {
112+ const link = document . createElement ( 'a' ) ;
113+ link . href = URL . createObjectURL ( await instance . toBlob ( ) ) ;
114+ link . download = `exportedMessages-${ new Date ( ) . toISOString ( ) } .pdf` ;
115+ document . body . appendChild ( link ) ;
116+ link . click ( ) ;
117+ document . body . removeChild ( link ) ;
118+ URL . revokeObjectURL ( link . href ) ;
119+ resolve ( ) ;
120+ } ;
75121
76- try {
77- instance . on ( 'change' , callback ) ;
78- instance . updateContainer ( jsx ) ;
79- } finally {
80- instance . removeListener ( 'change' , callback ) ;
81- }
122+ try {
123+ instance . on ( 'change' , callback ) ;
124+ instance . updateContainer ( jsx ) ;
125+ } catch ( error ) {
126+ reject ( error ) ;
127+ } finally {
128+ instance . removeListener ( 'change' , callback ) ;
129+ }
130+ } ) ;
131+ } ,
132+ onError : ( error ) => {
133+ dispatchToastMessage ( { type : 'error' , message : error } ) ;
134+ } ,
135+ onSuccess : ( ) => {
136+ dispatchToastMessage ( { type : 'success' , message : t ( 'Messages_exported_successfully' ) } ) ;
82137 } ,
83138 } ) ;
84139} ;
0 commit comments