@@ -49,8 +49,13 @@ async function fileInputChange(event) {
4949    const  files  =  input . files ; 
5050    let  selected  =  inputs . get ( input )  ||  new  Map ( ) 
5151    for  ( let  i  =  0 ;  i  <  files . length ;  i ++ )  { 
52-         let  fileId  =  await  getFileId ( files [ i ] ,  selected ) 
53-         selected . set ( fileId ,  {  handle,  file : files [ i ]  } ) 
52+         files [ i ] . input  =  input 
53+         files [ i ] . id  =  await  getFileId ( files [ i ] ) 
54+         if  ( selected . has ( files [ i ] . id ) )  { 
55+             console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
56+         } 
57+ 
58+         selected . set ( files [ i ] . id ,  files [ i ] ) 
5459    } 
5560    inputs . set ( input ,  selected ) ; 
5661    console . log ( "FileList:" ,  Array . from ( selected . values ( ) ) ) ; 
@@ -66,9 +71,15 @@ async function selectFile(event) {
6671        const  selectedFiles  =  await  window . showOpenFilePicker ( {  multiple } ) ; 
6772
6873        for  ( const  handle  of  selectedFiles )  { 
69-             let  file  =  handle . getFile ( ) 
70-             let  fileId  =  await  getFileId ( file ,  selected ) 
71-             selected . set ( fileId ,  {  handle,  file } ) 
74+             let  file  =  await  handle . getFile ( ) 
75+             file . input  =  input 
76+             file . id  =  await  getFileId ( file ) 
77+             if  ( selected . has ( file . id ) )  { 
78+                 console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
79+             } 
80+ 
81+             file . handle  =  handle 
82+             selected . set ( file . id ,  file ) 
7283        } 
7384
7485        if  ( selected . size )  { 
@@ -98,21 +109,35 @@ async function selectDirectory(event) {
98109            type : 'text/directory' , 
99110            'content-type' : 'text/directory' 
100111        } 
112+         file . input  =  input 
113+         file . id  =  await  getFileId ( file ) 
114+         if  ( selected . has ( file . id ) )  { 
115+             console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
116+         } 
101117
102-         file . id  =  await   getFileId ( file ,   selected ) 
103-         selected . set ( file . id ,  {  handle ,   file  } ) 
118+         file . handle  =  handle 
119+         selected . set ( file . id ,  file ) 
104120
105121        const  handles  =  await  getSelectedDirectoryHandles ( handle ,  handle . name ) 
106122        for  ( let  i  =  0 ;  i  <  handles . length ;  i ++ )  { 
107123            let  file  =  handles [ i ] 
108124            if  ( handles [ i ] . kind  ===  'file' )  { 
109125                file  =  await  handles [ i ] . getFile ( ) ; 
110-                 file  =  {  ...file ,  ...handles [ i ]  } 
126+                 file . directory  =  handles [ i ] . directory 
127+                 file . parentDirectory  =  handles [ i ] . parentDirectory 
128+                 file . path  =  handles [ i ] . path 
111129            } 
112130
131+             file . input  =  input 
132+             file . id  =  await  getFileId ( file ) 
133+             if  ( selected . has ( file . id ) )  { 
134+                 console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
135+             } 
136+ 
137+             file . handle  =  handles [ i ] 
113138            file [ 'content-type' ]  =  file . type 
114-              file . id   =   await   getFileId ( file ,   selected ) 
115-             selected . set ( file . id ,  {   handle :  handles [ i ] ,   file  } ) 
139+ 
140+             selected . set ( file . id ,  file ) 
116141        } 
117142
118143        if  ( selected . size )  { 
@@ -156,28 +181,27 @@ async function getFileId(file, selected) {
156181        const  {  name,  size,  type,  lastModified }  =  file ; 
157182        const  key  =  `${ name } ${ size } ${ type } ${ lastModified }  ; 
158183
159-         if  ( selected . has ( key ) )  { 
160-             console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
161-         } 
162- 
163184        file . id  =  key 
164185        return  key ; 
165186    } 
166187} 
167188
168- async  function  getFiles ( fileInputs )  { 
189+ async  function  getFiles ( fileInputs ,   isGetData )  { 
169190    const  files  =  [ ] ; 
170191
171192    if  ( ! Array . isArray ( fileInputs ) ) 
172193        fileInputs  =  [ fileInputs ] 
173194
174195    for  ( let  input  of  fileInputs )  { 
175196        const  selected  =  inputs . get ( input ) 
176-         for  ( const  value  of  selected . values ( ) )  { 
177-             let  file  =  await  readFile ( value . file ) 
178-             file  =  getData ( {  ...file  } ) 
179-             files . push ( file ) 
180-         } 
197+         if  ( selected ) 
198+             for  ( let  file  of  selected . values ( ) )  { 
199+                 if  ( ! file . src ) 
200+                     file  =  await  readFile ( file ) 
201+                 if  ( isGetData  !==  false ) 
202+                     file  =  getData ( {  ...file  } ) 
203+                 files . push ( file ) 
204+             } 
181205    } 
182206
183207    return  files 
@@ -256,26 +280,36 @@ function readFile(file) {
256280    } ) ; 
257281} 
258282
259- async  function  getNewFileHandle ( )  { 
260-     // const options = { 
261-     //     types: [ 
262-     //         { 
263-     //             description: 'Text Files', 
264-     //             accept: { 
265-     //                 'text/plain': ['.txt'], 
266-     //             }, 
267-     //         }, 
268-     //     ], 
269-     // }; 
270-     const  handle  =  await  window . showSaveFilePicker ( options ) ; 
271-     return  handle ; 
283+ async  function  renderFiles ( input )  { 
284+     let  template_id  =  input . getAttribute ( 'template_id' ) 
285+     if  ( template_id )  { 
286+         let  template  =  document . querySelector ( `[template="${ template_id }  ) 
287+         template . setAttribute ( 'file_id' ,  '{{id}}' ) 
288+         const  data  =  await  getFiles ( input ,  false ) 
289+         if  ( ! data . length )  return 
290+         render . data ( { 
291+             selector : `[template='${ template_id }  , 
292+             data
293+         } ) ; 
294+     } 
272295} 
273296
274- async  function  fileAction ( btn ,  params ,  action )  { 
297+ async  function  fileFormAction ( btn ,  params ,  action )  { 
275298    const  form  =  btn . closest ( 'form' ) 
276299    let  inputs  =  form . querySelectorAll ( 'input[type="file"]' ) 
277300    for  ( let  i  =  0 ;  i  <  inputs . length ;  i ++ )  { 
278-         await  save ( inputs [ i ] ) 
301+         if  ( action  ===  'upload' ) 
302+             upload ( inputs [ i ] ) 
303+         else  if  ( action  ===  'saveLocally'  ||  action  ===  'saveAs' )  { 
304+             save ( inputs [ i ] ) 
305+         } 
306+         else  if  ( action  ===  'export' )  { 
307+             // Export(inputs[i]) 
308+         } 
309+         else  if  ( action  ===  'import' )  { 
310+             // Import(inputs[i]) 
311+         }  else  { 
312+         } 
279313    } 
280314
281315    document . dispatchEvent ( new  CustomEvent ( action ,  { 
@@ -284,7 +318,96 @@ async function fileAction(btn, params, action) {
284318
285319} 
286320
321+ async  function  fileRenderAction ( btn ,  params ,  action )  { 
322+     let  file_id  =  btn . getAttribute ( 'file_id' ) ; 
323+     if  ( ! file_id )  { 
324+         const  closestElement  =  btn . closest ( '[file_id]' ) ; 
325+         if  ( closestElement )  { 
326+             file_id  =  closestElement . getAttribute ( 'file_id' ) ; 
327+         } 
328+     } 
329+     if  ( ! file_id )  return 
330+ 
331+     let  templateid  =  btn . closest ( '[templateid]' ) 
332+     if  ( templateid ) 
333+         templateid  =  templateid . getAttribute ( 'templateid' ) 
334+ 
335+     const  input  =  document . querySelector ( `[type="file"][template_id="${ templateid }  ) 
336+     if  ( ! input )  return 
337+ 
338+     let  file  =  inputs . get ( input ) . get ( file_id ) 
339+     if  ( ! file )  return 
340+ 
341+     if  ( action  ===  'createFile' )  { 
342+         let  name  =  btn . getAttribute ( 'value' ) 
343+         create ( file ,  'file' ,  name ) 
344+     } 
345+     else  if  ( action  ===  'deleteFile' ) 
346+         Delete ( file ) 
347+     else  if  ( action  ===  'createDirectory' )  { 
348+         let  name  =  btn . getAttribute ( 'value' ) 
349+         create ( file ,  'directory' ,  name ) 
350+     } 
351+     else  if  ( action  ===  'deleteDirectory' ) 
352+         Delete ( file ) 
353+ 
354+     document . dispatchEvent ( new  CustomEvent ( action ,  { 
355+         detail : { } 
356+     } ) ) ; 
357+ 
358+ } 
359+ 
287360async  function  save ( input )  { 
361+     try  { 
362+         let  files  =  await  getFiles ( input ) 
363+ 
364+         for  ( let  i  =  0 ;  i  <  files . length ;  i ++ )  { 
365+             if  ( ! files [ i ] . src )  continue 
366+ 
367+             if  ( files [ i ] . handle )  { 
368+                 if  ( 'saveAs'  ==  'true' )  { 
369+                     if  ( files [ i ] . kind  ===  'file' )  { 
370+                         const  options  =  { 
371+                             suggestedName : files [ i ] . name , 
372+                             types : [ 
373+                                 { 
374+                                     description : 'Text Files' , 
375+                                 } 
376+                             ] , 
377+                         } ; 
378+                         files [ i ] . handle  =  await  window . showSaveFilePicker ( options ) ; 
379+                     }  else  if  ( files [ i ] . kind  ===  'directory' )  { 
380+                         // Create a new subdirectory 
381+                         files [ i ] . handle  =  await  files [ i ] . handle . getDirectoryHandle ( 'new_directory' ,  {  create : true  } ) ; 
382+                         return 
383+                     } 
384+                 } 
385+ 
386+                 const  writable  =  await  files [ i ] . handle . createWritable ( ) ; 
387+                 await  writable . write ( files [ i ] . src ) ; 
388+                 await  writable . close ( ) ; 
389+ 
390+             }  else  { 
391+                 const  blob  =  new  Blob ( [ files [ i ] . src ] ,  {  type : files [ i ] . type  } ) ; 
392+ 
393+                 // Create a temporary <a> element to trigger the file download 
394+                 const  downloadLink  =  document . createElement ( 'a' ) ; 
395+                 downloadLink . href  =  URL . createObjectURL ( blob ) ; 
396+                 downloadLink . download  =  files [ i ] . name ; 
397+ 
398+                 // Trigger the download 
399+                 downloadLink . click ( ) ; 
400+             } 
401+ 
402+         } 
403+     }  catch  ( error )  { 
404+         if  ( error . name  !==  'AbortError' )  { 
405+             console . error ( "Error selecting files:" ,  error ) ; 
406+         } 
407+     } 
408+ } 
409+ 
410+ async  function  upload ( input )  { 
288411    let  collection  =  input . getAttribute ( 'collection' ) 
289412    let  document_id  =  input . getAttribute ( 'document_id' ) 
290413    let  files  =  await  getFiles ( input ) 
@@ -309,17 +432,63 @@ async function save(input) {
309432    return  response 
310433} 
311434
312- async  function  renderFiles ( input )  { 
313-     let  template_id  =  input . getAttribute ( 'template_id' ) 
314-     if  ( template_id )  { 
315-         let  template  =  document . querySelector ( `[template="${ template_id }  ) 
316-         template . setAttribute ( 'file_id' ,  '{{id}}' ) 
317-         const  data  =  await  getFiles ( input ) 
318-         if  ( ! data . length )  return 
319-         render . data ( { 
320-             selector : `[template='${ template_id }  , 
321-             data
322-         } ) ; 
435+ async  function  create ( directory ,  type ,  name ,  src  =  "" )  { 
436+     try  { 
437+         if  ( directory . handle  &&  directory . input )  { 
438+             if  ( ! name )  { 
439+                 const  name  =  prompt ( 'Enter the file name:' ) ; 
440+                 if  ( ! name )  { 
441+                     console . log ( 'Invalid file name.' ) ; 
442+                     return ; 
443+                 } 
444+ 
445+             } 
446+ 
447+             let  handle ,  file 
448+             if  ( type  ===  'directory' )  { 
449+                 handle  =  await  directory . handle . getDirectoryHandle ( name ,  {  create : true  } ) ; 
450+                 file  =  {  name : handle . name ,  type : 'text/directory'  } 
451+             }  else  if  ( type  ===  'file' )  { 
452+                 handle  =  await  directory . handle . getFileHandle ( name ,  {  create : true  } ) ; 
453+                 const  writable  =  await  handle . createWritable ( ) ; 
454+ 
455+                 // Write data to the new file... 
456+                 await  writable . write ( src ) ; 
457+                 await  writable . close ( ) ; 
458+ 
459+                 file  =  handle . getFile ( ) 
460+             } 
461+ 
462+             if  ( directory . input )  { 
463+                 file . directory  =  directory . path 
464+                 file . parentDirectory  =  directory . name 
465+                 file . path  =  directory . path  +  '/'  +  file . name 
466+                 file . input  =  directory . input 
467+                 file . handle  =  handle 
468+                 file [ 'content-type' ]  =  file . type 
469+ 
470+                 file . id  =  await  getFileId ( file ) 
471+                 if  ( inputs . get ( directory . input ) . has ( file . id ) )  { 
472+                     console . log ( 'Duplicate file has been selected. This could be in error as the browser does not provide a clear way of checking duplictaes' ) 
473+                 } 
474+ 
475+                 inputs . get ( directory . input ) . set ( file . id ,  file ) 
476+             } 
477+         } 
478+     }  catch  ( error )  { 
479+         console . log ( 'Error adding file:' ,  error ) ; 
480+     } 
481+ } 
482+ 
483+ async  function  Delete ( file )  { 
484+     try  { 
485+         if  ( file . handle )  { 
486+             await  file . handle . remove ( ) ; 
487+             if  ( file . input  &&  file . id ) 
488+                 inputs . get ( file . input ) . delete ( file . id ) 
489+         } 
490+     }  catch  ( error )  { 
491+         console . log ( 'Error deleting file:' ,  error ) ; 
323492    } 
324493} 
325494
@@ -350,10 +519,44 @@ observer.init({
350519action . init ( { 
351520    name : "upload" , 
352521    callback : ( btn ,  params )  =>  { 
353-         fileAction ( btn ,  params ,  "upload" ) 
522+         fileFormAction ( btn ,  params ,  "upload" ) 
523+     } 
524+ } ) 
525+ 
526+ action . init ( { 
527+     name : "saveLocally" , 
528+     callback : ( btn ,  params )  =>  { 
529+         fileFormAction ( btn ,  params ,  "saveLocally" ) 
530+     } 
531+ } ) 
532+ 
533+ action . init ( { 
534+     name : "createFile" , 
535+     callback : ( btn ,  params )  =>  { 
536+         fileRenderAction ( btn ,  params ,  "createFile" ) 
537+     } 
538+ } ) 
539+ 
540+ action . init ( { 
541+     name : "deleteFile" , 
542+     callback : ( btn ,  params )  =>  { 
543+         fileRenderAction ( btn ,  params ,  "deleteFile" ) 
544+     } 
545+ } ) 
546+ action . init ( { 
547+     name : "createDirectory" , 
548+     callback : ( btn ,  params )  =>  { 
549+         fileRenderAction ( btn ,  params ,  "createDirectory" ) 
550+     } 
551+ } ) 
552+ 
553+ action . init ( { 
554+     name : "deleteDirectory" , 
555+     callback : ( btn ,  params )  =>  { 
556+         fileRenderAction ( btn ,  params ,  "deleteDirectory" ) 
354557    } 
355558} ) 
356559
357560init ( ) 
358561
359- export  default  {  getFiles } 
562+ export  default  {  getFiles,  create ,  Delete  } 
0 commit comments