1- import React , { FunctionComponent , useCallback , useMemo , useState } from 'react' ;
1+ import React , { ClipboardEventHandler , FunctionComponent , useCallback , useMemo , useState } from 'react' ;
22import PageContainer from '../../layouts/pages/pageContainer/PageContainer' ;
33import styles from './DataUrlPage.module.scss' ;
44import { Button , Col , Input , notification , Space , Switch , Upload } from 'antd' ;
@@ -17,29 +17,36 @@ import { UploadFile } from 'antd/lib/upload/interface';
1717import getErrorMessage from '../../utils/getErrorMessage' ;
1818import { Base64 } from 'js-base64' ;
1919import readFileAsBase64 from '../../utils/readFileAsBase64' ;
20+ import CopyButton from '../../components/copyButton/CopyButton' ;
2021
2122interface DataUrlState {
2223 title : string ;
2324 mimeType : string ;
2425 encoding : string ;
2526 content : string ;
2627 isBase64 : boolean ;
28+ isAutoBase64 : boolean ;
2729}
2830
2931const initialState : DataUrlState = {
3032 title : '' ,
3133 mimeType : 'text/plain' ,
3234 encoding : 'utf-8' ,
3335 content : 'Hello World' ,
34- isBase64 : false
36+ isBase64 : false ,
37+ isAutoBase64 : false
3538} ;
3639
3740const getDataUrlQueryParams = ( state : DataUrlState ) : DataUrlViewPageQueryParams => {
3841 // data:[<MIME-type>][;charset=<encoding>][;base64],<data>
3942
43+ const isAutoBase64 = state . isAutoBase64 && ! state . isBase64 ;
44+ const isBase64 = state . isBase64 || isAutoBase64 ;
45+ const content = isAutoBase64 ? Base64 . encode ( state . content ) : state . content ;
46+
4047 const charsetPart = state . encoding && `;charset=${ state . encoding } ` ;
41- const base64Part = state . isBase64 ? ';base64' : '' ;
42- const dataPart = `,${ state . content } ` ;
48+ const base64Part = isBase64 ? ';base64' : '' ;
49+ const dataPart = `,${ content } ` ;
4350
4451 const data = `data:${ state . mimeType } ${ charsetPart } ${ base64Part } ${ dataPart } ` ;
4552
@@ -91,33 +98,60 @@ const DataUrlPage: FunctionComponent = () => {
9198 const encodeBase64Content = useCallback ( ( ) => transformContent ( Base64 . encode ) , [ transformContent ] ) ;
9299 const decodeBase64Content = useCallback ( ( ) => transformContent ( Base64 . decode ) , [ transformContent ] ) ;
93100
94- const handleFileChange = useCallback ( async ( info : UploadChangeParam < UploadFile < unknown > > ) => {
95- const { file } = info ;
96-
97- if ( file . status !== 'done' ) {
98- return ;
99- }
100-
101- const { name, type } = file ;
102-
103- const blob = file . originFileObj ;
104-
101+ const handleFileChange = useCallback ( async ( blob : Blob , name : string ) => {
105102 const content = ( blob && ( await readFileAsBase64 ( blob ) ) ) ?? '' ;
106103
107104 setState ( {
108105 title : name ,
109- mimeType : type ?? '' ,
106+ mimeType : blob . type ?? '' ,
110107 isBase64 : true ,
108+ isAutoBase64 : false ,
111109 encoding : '' ,
112110 content
113111 } ) ;
114112 } , [ ] ) ;
115113
114+ const handleUploadedFileChange = useCallback (
115+ async ( info : UploadChangeParam < UploadFile < unknown > > ) => {
116+ const { file } = info ;
117+
118+ if ( file . status !== 'done' ) {
119+ return ;
120+ }
121+
122+ const blob = file . originFileObj ;
123+
124+ if ( ! blob ) {
125+ return ;
126+ }
127+
128+ await handleFileChange ( blob , file . name ) ;
129+ } ,
130+ [ handleFileChange ]
131+ ) ;
132+
133+ const handleContentPaste = useCallback < ClipboardEventHandler < HTMLTextAreaElement > > (
134+ async ( event ) => {
135+ const file = event . clipboardData . files [ 0 ] ;
136+
137+ if ( file === undefined ) {
138+ return ;
139+ }
140+
141+ await handleFileChange ( file , file . name ) ;
142+ } ,
143+ [ handleFileChange ]
144+ ) ;
145+
116146 return (
117147 < PageContainer title = "Data URL Generator" >
118148 < Col xs = { 24 } lg = { 18 } xl = { 12 } className = { styles . container } >
119149 < Space className = "mb-2" >
120- < Upload customRequest = { dummyAntdUploadRequest } onChange = { handleFileChange } showUploadList = { false } >
150+ < Upload
151+ customRequest = { dummyAntdUploadRequest }
152+ onChange = { handleUploadedFileChange }
153+ showUploadList = { false }
154+ >
121155 < Button icon = { < UploadOutlined /> } > Upload file</ Button >
122156 </ Upload >
123157 </ Space >
@@ -141,21 +175,33 @@ const DataUrlPage: FunctionComponent = () => {
141175 value = { state . content }
142176 onChange = { handleStateChange ( 'content' ) }
143177 rows = { 3 }
178+ showCount
179+ onPaste = { handleContentPaste }
180+ allowClear
144181 />
145- < Space className = "mt-2" >
182+ < Space className = "mt-2" wrap >
146183 < Button onClick = { encodeBase64Content } > Encode base64</ Button >
147184 < Button onClick = { decodeBase64Content } > Decode base64</ Button >
148185 </ Space >
149186 < label className = { classNames ( styles . formItem , 'mt-2' ) } >
150187 < Switch checked = { state . isBase64 } onChange = { handleStateChange ( 'isBase64' ) } />
151188 < span className = "ms-3" > Base64</ span >
152189 </ label >
190+ < label className = { classNames ( styles . formItem , 'mt-2' ) } >
191+ < Switch
192+ checked = { state . isAutoBase64 && ! state . isBase64 }
193+ onChange = { handleStateChange ( 'isAutoBase64' ) }
194+ disabled = { state . isBase64 }
195+ />
196+ < span className = "ms-3" > Auto convert text to base64</ span >
197+ </ label >
153198 </ div >
154199 </ label >
155- < Link to = { dataUrlViewUrl } className = "mt-3" ref = { dataUrlViewLinkRef } >
200+ < Link to = { dataUrlViewUrl } target = "_blank" className = "mt-3" ref = { dataUrlViewLinkRef } >
156201 View the iframe
157202 </ Link >
158- < TextArea readOnly value = { displayedDataUrlViewUrl } rows = { 4 } />
203+ < TextArea readOnly value = { displayedDataUrlViewUrl } rows = { 4 } showCount />
204+ < CopyButton value = { displayedDataUrlViewUrl } className = { styles . copyButton } />
159205 </ Col >
160206 </ PageContainer >
161207 ) ;
0 commit comments