Page 1 of 1

File System Access API

Posted: Wed Dec 01, 2021 2:47 pm
by Peter
The File System Access API allows web apps to read or save changes directly to files and folders on the user's device.
More Info: https://web.dev/file-system-access/

Code: Select all

EnableExplicit

Global FileHandle

Enumeration
  #Window
  #LoadButton
  #SaveButton
  #SaveAsButton
  #Editor
EndEnumeration

Procedure IsUndefined(Object)
  ! return typeof v_object === "undefined";
EndProcedure

Procedure IsDefined(Object)
  ! return typeof v_object !== "undefined";
EndProcedure

Procedure WriteFile(FileHandle, Content.s)
  ! (async() => {
  !   // Create a FileSystemWritableFileStream to write to.
  !   const writable = await v_filehandle.createWritable();
  !   // Write the contents of the file to the stream.
  !   await writable.write(v_content);
  !   // Close the file and write the contents to disk.
  !   await writable.close();
  ! })(v_filehandle, v_content);
EndProcedure


Procedure LoadButtonEvent()
  
  Protected FileContent.s
  
  ! (async() => {
  !   [v_filehandle] = await window.showOpenFilePicker();
  !   const file     = await v_filehandle.getFile();
  !   v_filecontent  = await file.text();
  SetGadgetText(#Editor, FileContent)
  SetActiveGadget(#Editor)
  ! })();  
  
EndProcedure

Procedure SaveAsButtonEvent()
  
  Protected FileContent.s = GetGadgetText(#Editor)
  
  ! (async() => {
  !   const options = {
  !     types: [
  !       {
  !         description: 'Text Files',
  !         accept: {
  !           'text/plain': ['.txt'],
  !         },
  !       },
  !     ],
  !   };
  !   v_filehandle = await window.showSaveFilePicker(options);
  
  If IsDefined(FileHandle)
    WriteFile(FileHandle, FileContent)
  EndIf 
  
  ! })();  
  
EndProcedure

Procedure SaveButtonEvent()
  
  If IsUndefined(FileHandle) Or FileHandle = 0
    SaveAsButtonEvent()
    ProcedureReturn
  EndIf
  
  Protected FileContent.s = GetGadgetText(#Editor)
  
  WriteFile(FileHandle, FileContent)
  
EndProcedure

OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 800, 600, "Native FileSystem - Demo", #PB_Window_ScreenCentered)

ButtonGadget(#LoadButton,    10, 10, 80, 30, "Load")
ButtonGadget(#SaveButton,   100, 10, 80, 30, "Save")
ButtonGadget(#SaveAsButton, 190, 10, 80, 30, "Save as...")

EditorGadget(#Editor, 10, 50, WindowWidth(#Window) - 20, WindowHeight(#Window) - 60)

BindGadgetEvent(#LoadButton,   @LoadButtonEvent())
BindGadgetEvent(#SaveButton,   @SaveButtonEvent())
BindGadgetEvent(#SaveAsButton, @SaveAsButtonEvent())

Re: File System Access API

Posted: Thu Dec 02, 2021 3:49 am
by useful
Wow! How cool. Do you have any idea how to convert this example for graphic files (jpj,png,...)?

Re: File System Access API

Posted: Fri Dec 03, 2021 10:19 am
by Peter
useful wrote: Thu Dec 02, 2021 3:49 amWow! How cool. Do you have any idea how to convert this example for graphic files (jpj,png,...)?
for loadings images try this one:

Code: Select all

EnableExplicit

Procedure LoadImageFromFilesystem(ImageGadget)
  
  If IsGadget(ImageGadget) And GadgetType(ImageGadget) = #PB_GadgetType_Image
    
    ! (async() => {
    !   const [filehandler] = await window.showOpenFilePicker();
    !   var file = await filehandler.getFile();
    !   var filereader = new FileReader();
    !   filereader.readAsDataURL(file);
    !   filereader.onload = function() {
    !     var img = new Image;
    !     img.onload = function() {
    !       var gadgetid = spider_GadgetID(v_imagegadget);
    !       var canvas = gadgetid.gadget.children[0];
    !       spider_ResizeGadget(v_imagegadget, -65535, -65535, img.width, img.height);
    !       canvas.width = spider_GadgetWidth(v_imagegadget);
    !       canvas.height = spider_GadgetHeight(v_imagegadget);
    !       var context = canvas.getContext("2d");  
    !       context.clearRect(0, 0, canvas.width, canvas.height);
    !       context.drawImage(img, 0, 0);
    !     };
    !     img.src = filereader.result;
    !   }
    ! })();
    
  EndIf
  
EndProcedure

Enumeration
  #Window
  #ButtonGadget
  #ImageGadget
EndEnumeration

Procedure ButtonEvent()
  LoadImageFromFilesystem(#ImageGadget)
EndProcedure

OpenWindow(#Window, 0, 0, 800, 800, "ImageGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(#ButtonGadget, 10, 10, 100, 30, "Load image...")
ImageGadget(#ImageGadget,  10, 50, 500, 500, 0, #PB_Image_Border)

BindGadgetEvent(#ButtonGadget, @ButtonEvent())

Re: File System Access API

Posted: Fri Dec 03, 2021 10:40 am
by useful
Thank you very much.

Re: File System Access API

Posted: Sun Jun 11, 2023 7:41 am
by jn2002dk
Beyond awesome

I tried using it with audio files but i am doing something wrong

Code: Select all

InitSound()
Global Song.s
Global fsong=LoadSound(0, "track_2.mp3")

Procedure LoadButtonEvent()

    ! (async() => {
    !   const [filehandler] = await window.showOpenFilePicker();
    !   var file = await filehandler.getFile();
    !   var filereader = new FileReader();
    !   filereader.readAsDataURL(file);
    !   filereader.onload = function() {
    !   g_song = file.webkitRelativePath;
Debug Song
    !   }
    ! })();
EndProcedure
In this case i want the filepath so i can load it into fsong and play it but i am missing something

Re: File System Access API

Posted: Sun Jul 16, 2023 12:01 am
by tj1010
SB already has the user-interaction file API integrated(OpenFileRequester and ReadFileCallback). To do anything without user clicks you gotta use the Cordova File plugin; I already posted SB code for it. Browsers and App engines that use CORS UI/UX based stuff will always require user prompts.

I use the SB prompt stuff for loading sqlite databases on Windows 11 and Android 13 on one tool, and then the File Cordova plugin everywhere else for no prompts. On mobile devices you're going to be restricted to certain directories without permissions that can only be set in a manifest..