TMS WEB Core embraces ever more powerful PWA support from Google Chrome
There is no doubt that Google is and remains the driving force behind the fast evolving web world. And with Microsoft having adopted the Google Chromium engine in its latest and new default Windows 10 operating system browser, it is clear that the browser gets ever more powerful with each release.
While every Chrome update sees a lot of enhancements, the release 86 introduced perhaps another disruptive feature: the file system access API!
Yes, you read this correct, file system access API or in other words, access to the local file system from a PWA (Progressive Web App)! Of course, Google took the necessary measures to look over security. I can imagine you wouldn’t want to be directed to some URL and the web application at this URL will suddenly start scanning your local hard drive.
All local file access remains initiated by user interaction and user consent!
User consent prompt to view files in a folder
What the File System Access API actually provides is:
- open local text or binary files
- save to a local text or binary files
- use the operating system file dialog to pick a file
- use the operating system file dialog to save to a file
- get access to a folder and its files/subfolders
- use the operating system to select a folder
- associate file types with PWA apps
Now, you will understand that as we read the news, we were eager to investigate integration capabilities in a TMS WEB Core PWA and reflect on bringing easy to use Pascal language wrapper classes to take advantage of this new functionality.
So, in our labs, we created a support unit for local file handling : WEBLib.LocalFiles. In this unit, three classes are available: TTextFile, TBinaryFile and TFolder.
Working with local text files
TTextFile offers following public interface
TTextFile = class(TObject) public procedure OpenFile; overload; procedure OpenFile(AOpenFile: TOpenTextFileProc); overload; procedure SaveFile; overload; procedure SaveFile(ASaveFile: TSaveFileProc); overload; procedure SaveAsFile; overload; procedure SaveAsFile(ASaveFile: TSaveFileProc); overload; property Text: string; property FileName: string; property OnFileOpen: TNotifyEvent; property OnFileSave: TNotifyEvent; end;
As you can see there are overloads for the OpenFile, SaveFile and SaveAsFile methods. In one version of the methods, there is an anonymouse method that is called when the action on the file completed and the other versioni will signal completion via an event.
To use the class to open a file, we can write:
begin ATextFile := TTextFile.Create; ATextFile.OpenFile(procedure(AText: string) begin WebMemo1.Lines.Text := AText; end); end;
If the text was modified in the memo control, it can be saved with following code working on the same instance of the TTextFile object:
begin ATextFile.Text := WebMemo1.Lines.Text; ATextFile.SaveFile(procedure begin ShowMessage('File succesfully saved'); end); end;
As you can see, it becomes extremely easy for Pascal developers to take advantage of the file system access API in the browser!
Working with local binary files
For binary files, a similar class TBinaryFile was created with the important different from the TTextFile that here the data read or to be saved is of the type TJSArrayBuffer. TJSArrayBuffer is the Object Pascal wrapper for the JavaScript ArrayBuffer which basically is an array of bytes.
The interface of TBinaryFile is the same as TTextFile except that it exposes public property
TBinaryFile.Data: TJSArrayBuffer.
To demonstrate its use, we can open a local image file with the following code:
var base64String: string; begin ABinaryFile.OpenFile(procedure(AValue: TJSArrayBuffer) begin base64string := ArrayBufferToBase64(AValue); base64string := 'data:image/jpeg;base64,'+base64String; WebImageControl1.URL := base64string; end); end;
As you can see, the image file binary data is received via the TJSArrayBuffer and we neeed to convert it to a base64 dataURL in order to visualize it in a TWebImageControl.
Saving an image is equally simple:
begin ABinaryFile.Data := Base64ToArrayBuffer(WebImageControl1.Base64Image); ABinaryFile.SaveAsFile(procedure begin ShowMessage('File succesfully saved'); end); end;
Working with folders
Next is working with folders. The File system access API offers a way to show the operating system folder to select a folder. Once access is given after picking the folder, the API enables to retrieve all files and folders in the selected folder. As such, we can get access to all files in this folder or even open a subfolder and query all files in the subfolder. As there is folder access, we have also the capability to get access to all files in the folder.
The TFolder class has following public interface
TFolder = aclass(TObject) public procedure Open; overload; procedure Open(AOpenFolder: TOpenFolderProc); overload; procedure CreateFolder(AName: string); procedure CreateFile(AName: string); procedure GetFile(AName: string; GetFile: TGetFileProc); procedure GetFolder(AName: string; GetFolder: TGetFolderProc); property Files: TFileSystemFileHandleArray; published property OnFolderOpen: TNotifyEvent read FOnFolderOpen write FOnFolderOpen; end;
So, to let the user select a folder and list all files in the folder, we could do:
var AFolder: TFolder; l: integer; begin AFolder := TFolder.Create; AFolder.Open(procedure begin for l := 0 to Length(AFolder.Files) - 1 do WebListBox1.Items.Add(AFolder.Files[l].Name); end); end;
As a proof of concept, we created three PWA’s with TMS WEB Core. One is a local folder browser, the other is a code editor you can use the edit local files (including .PAS files) and the third is a photo editor that allows you to take advantage of web technology to change hue, brightness, contrast, … of pictures and save the modified version.
You can find the demos here
Folder file browser
https://www.tmssoftware.com/pwa/filebrowser
Code editor
https://www.tmssoftware.com/pwa/codeeditor
Image editor
https://www.tmssoftware.com/pwa/imageeditor
Click image to see the image editor in action
We are further fine-tuning and polishing our easy to use Object Pascal wrappers for the file system API and you can expect this and way bigger things in the next major release of TMS WEB Core. Note that all this functionality will be possible from TMS WEB Core from Delphi, from Visual Studio Code and also from Lazarus.
We are eager to learn what great ideas you have for PWAs developed with TMS WEB Core and hear your comments, feedback and wishes for further developments in the comments on this blog.