Jump to content

How to create a uniGui PWA


Norm

Recommended Posts

Hi guys,

There has been a lot of conflicting information on the forum about whether uniGui can create PWA apps and how to go about turning your app into a PWA. I have done quite a bit of work with PWA’s and I am hoping that this post will clarify the issue and provide easy-to-follow guidelines for those who are interested. To make the process easier I have selected a simple demo app that comes with uniGui and uploaded it for you after converting it to PWA.  You can use the url below to see the resulting PWA on any device.

https://www.qssldtf.com:8086

The answer to whether uniGui is PWA capable depends very much on what aspect of PWA you are looking for. Clearly there is no doubt that any uniGui app can be made installable on all devices that support PWA technology. This includes all mobile devices as well as desktops running Chrome or MS Edge. Firefox & Opera support aspects of PWA but do not allow installation. And simply making your app installable makes such a massive a difference to ease of use (no browser, faster launch, full-screen, smooth navigation etc.) that there should be no excuse why you would not want to do it. How easily this can be done depends on the deployment option you have chosen. More to this below.

The other aspects of PWA (offline operation, push notification & access to device resources) are, in my opinion, only achievable with uniGui if you build your UI with HTML and JavaScript because otherwise Ext JS puts too many stumbling blocks in the way.

There are 3 basic requirements to making your app a PWA:

  •         The site must be accessed via HTTPS with a valid SSL certificate.
  •         The site must have a valid web Manifest
  •         You must supply and register a Service Worker

 

HTTPS requirements

PWA sites will only work over a secure connection with a valid SSL. However, for development purposes Google Chrome allows you to bypass this requirement when working over localhost so you can easily debug and install the PWA on your development device. This feature is not a default setting in Chrome. You need to enable it via chrome://flags as explained here Options for testing service workers via HTTP.

 

Web Manifest

The web manifest is a text file that contains a single JSON object whose fields map out the essential settings of your PWA site. By convention the manifest usually has the filename manifest.json or manifest.webmanifest and must reside in the root folder of your app. It contains all the information needed to tell the browser how the PWA will look when it is installed on the target device and configures how it will behave when it is launched. The manifest must also point to a list of icons of varying sizes to be used on splash-screens of devices you are targeting. There is a wealth of information about the web manifest online so I won’t say anymore here, except to mention that this is where there is a stumbling block with uniGui, unless you are deploying via ISAPI. As many developers have discovered, it is impossible to import the manifest if your app is running in standalone mode, with or without hyper-server. You will consistently get the dreaded “401 (unauthorised)” error. However I managed to come up with a means to sneak the manifest in through the back-door and I will share that below.

 

Service Worker

The Service Worker is a piece of JavaScript code that runs in its own thread in the browser background and intercepts and routes all the communication between the client side of your app and both the server and the rest of the world.  You have tools to interrogate and manipulate this communication at will with JavaScript. You can immediately see how things like “working offline” and “push notifications” evolve from this. Every PWA running in the browser must register its own service worker. By convention the service worker has a filename like sw.js and usually reside in the root folder of your app. Depending on the desired functionality the service worker can be very complex or a simple stub that just relays messages without any interrogation. The service worker included in the demo project I have uploaded with this post is of the latter type and you can safely use it in all your apps. However, every service worker must have a unique “cache-name” so you need to edit the file and change the embedded cache-name to something that matches your app-name.

What is with Safari

At the point of this writing Safari does not yet support the web manifest. When you run you PWA on any Safari device the manifest is completely ignored. Instead, in order to get a PWA to work Safari requires that you insert some essential meta tags into the header of your html. It so happens that this anomaly with Safari makes it much easier to convert a uniGui app installable on Apple devices. Just give the app the little stub of service worker discussed above and add a tiny bit of JavaScript into the ServerModule.CustomCSS to activate it then add the following meta tags and into the ServerModule.CustomMeta and you have a working PWA for all Safari Devices. Gone is the “401 (unauthorised)” nightmare.

<meta name="apple-mobile-web-app-capable" content="yes">

<meta name="apple-mobile-web-app-status-bar-style" content="black">

<meta name="apple-mobile-web-title" content="Video Demo">

<meta name="apple-touch-icon" href="/files/icons/i144x144.png" sizes="144x144">

<meta name="apple-touch-icon" href="files/icons/i192x192.png" sizes="192x192"/>

<meta name="apple-touch-icon" href="files/icons/i152x152.png" sizes="152x152"/>

I continue to see recent articles online that tell you that in order to get your PWA to also work on Safari you have to insert these meta tags into your app. This is old news guys. This Safari issue was made redundant in April 2020 when Google introduced PWACompat.

This utility will look at your web manifest and automatically adjust the html of your app to satisfy Safari (and other legacy browsers). We’ll see how to use it below.

So how do you go about converting you uniGui to PWA

The components and bit of code you need are included in the project I have supplied so I suggest you start by downloading and compiling the project to get to grip with how things work. The project is very simple and should compile without any issues. Note that I have configured the project to store the resulting exe and dcu’s in their own folders because I prefer to keep the source folder uncluttered.

After compiling, run the app by double-clicking on the resulting exe then use Chrome to access http://localhost:8077. Don’t forget to configure Chrome to bypass HTTPS requirements as stated above beforehand.

Once the site has opened I suggest you activate Chrome’s dev-tools (F12 key) and switch to the “application” tab. There you can see that both the service worker and manifest have installed successfully and all the icons will be shown.

You should now also see an install button in the toolbar. Depending your version of Chrome, you might have to close and restart the site if you don’t see the install button.

Go ahead and run the install, it is very easy to uninstall later. The PWA should install immediately and switch over to a full-screen standalone application and the app icon should appear on your desktop. By the way, the easiest way to uninstall a PWA is to go to chrome://apps. All installed PWA’s will be shown and you can right-click to select the uninstall option. It might interest you to know that the PWA will also be registered as a valid Windows application in the Registry. So you can uninstall it by going to “Control Panel -> Programs & Features”.

Lets’ analyse the PWA components in the demo project

In the root folder of the executable you can see the following required files:

  • manifest.json
  • sw.js  (Service Worker)

We also have a list of splash-screen icons stored in the folder files/icons. That is in general all you need from a components point of view. In theory all you then need to do now is to import the manifest and register the service worker when the project starts up.

Importing the manifest

You do this by inserting this into ServerModule.CustomMeta:

<link rel="manifest" href="/manifest.json">

Registering the Service Worker

This is done with the bit of JavaScript shown below. You insert this into ServerModule.CustomCSS. As you can see, it is good practice to first check whether the host browser supports service workers before attempting to register. In the script I have supplied with the demo project I have inserted some logging (console.log) to show weather or not registration has succeeded. You can see the results in the “console” page of the dev-tools. You need to comment the log statements out before publishing your PWA app.

</style>

<script>

  if ('serviceWorker' in navigator) {

    navigator.serviceWorker.register('/sw.js')

  }

</script>

<style>

If you are deploying through ISAPI that is all you need to do. The site will work as a PWA in Android and Chrome. But not Safari. In order for Safari to work you need bring in the PWACompact utility discussed above. You do this by adding the pwacompat link in the ServerModule.CustomMeta entry, before the manifest link. So the CustomMeta entry will look like this (note I included the favicon injection that we all do):

<link rel="icon" type="image/png" href="files/icons/i192x192.png" sizes="192x192"/>

<meta name="apple-mobile-web-app-capable" content="yes">

<script async src="https://cdn.jsdelivr.net/npm/pwacompat" crossorigin="anonymous"></script>

<link rel="SHORTCUT ICON" href="/favicon.ico">

<link rel="manifest" href="/manifest.json">

Briefly, the PWACompat utility will analyse your manifest and insert additional meta links to satisfy Safari. You will them have a PWA that will work in all PWA compatible browsers.

But, as things stand, this will only work when deployed through ISAPI. If you are running in standalone mode the “manifest” link will fail with a “401 (unauthorized)” error and PWACompat will fail because it does not have a manifest to work with.

To fix this issue I borrowed an idea from here How to Setup Your Web App Manifest Dynamically Using Javascript and adjusted it to overcome some ExtJS quirks.

The trick here is to remove href="/manifest.json" from the manifest link in the CustomMeta script and replace it with a placeholder id that we can use later to inject a dynamic manifest. The manifest meta link now looks like this:

<link rel="manifest" id="manifest_link">

What I did for standalone deployment is to read the manifest in Delphi and generate some JavaScript that will be injected into the starting html. The resulting JavaScript must be inserted into the “Script” field of the form that activates first. If your application uses a Login form the script should will be inserted the LoginForm is activated, otherwise it has to be inserted into the MainForm. The project demo I have supplied does not have a Login form so the script is inserted as follows in the Main form:

procedure TUniLoginForm1.UniLoginFormCreate(Sender: TObject);

var

  sManifest : String;

begin

  sManifest := UniMainModule.GetDynamicManifest;

  if sManifest > '' then

    Self.Script.Text := sManifest;

end;

As the code indicates I have placed the required JavaScript generation code in the MainModule for ease of use. The UniModule.GetDynamicManifest function converts the contents of the manifest.json file into a JavaScript object and add the necessary java code that will modify the manifest link we added via CustomMeta (<link rel="manifest" id="manifest_link">) and insert an “href” that points to the new manifest object.

You will notice when you look at the manifest generation function that it first checks the manifest.json to make sure that it contains all the essential fields. I discovered by accident that Delphi’s JSON handling does not have decent exception handling and there is no way of avoiding a crash if you try to reference a field that does not exist. If your manifest.json does not conform you will get an empty JavaScript back and the PWA won’t work.

In case you want to see the resulting JavaScript I have added some code in the function to save it in the folder Config off the root folder. You just need to un-comment it.

Additionally, it is a habit of mine to use the ini file concept to configure my applications. This is what I have done regarding the CustomMeta and CustomCSS scripts. I store the changes I need in an external text file and import it at start-up. For this project I have stored the data in the folder “Config" within the root folder. This is the code I use to populate the ServerModule:

procedure TUniServerModule.UniGUIServerModuleCreate(Sender: TObject);

var

  sData, cfgFolder, cfgFile : String;

begin

  cfgFolder := ServerRoot+'config\';

//Import service worker registration

 cfgFile := cfgFolder + 'script.cfg';

  if FileExists(cfgFile) then

  with TStringList.Create do

  try

    LoadFromFile(cfgFile);

    sData := Text;

    if sData > '' then

      CustomCSS.Text := sData;

  finally

    free;

  end;

//Import manifest meta links

  cfgFile := cfgFolder + 'meta.cfg';

  if FileExists(cfgFile) then

  with TStringList.Create do

  try

    LoadFromFile(cfgFile);

    sData := Text;

    if sData > '' then

      CustomMeta.Text := sData;

  finally

    free;

  end;

end;

To summarise, these are the steps you need to do to convert an existing uniGui app to PWA:

  • Create a web manifest.json and place it in the root folder of your executable. I suggest you initially copy my manifest and change the “name”, “short_name” and start_url to fit your project. For standalone deployment the start_url should point to the project executable if you are not using the hyper-server, otherwise it should point to hyper_server.exe. For ISAPI it should point at the hyper-server dll, whatever you have called it.
    • 2 quick tips here:
      • The “name” in the manifest is used on the splash screen of mobiles and the caption of the MainForm when running on desktops. However what you have entered in the “name” field will be concatenated with whatever you have in the “Title” field of the ServerModule. So remember to blank the ServerModule’s Title field. FYI the “short_name” will be used on the home-screen icon of mobiles and shortcut icon of desktops, but only if the “name” is too long (I think >40 chars).
      • There are numerous online tools to help you create your icons. I use https://manifest-gen.netlify.app. You just need to upload a 512x512 image and it will generate all the icons you require.
  • Copy my sw.js into the executable root folder.

  • Copy the contents of my files/config folder into the files folder of your executable.
  • Copy the CustomMeta & CustomCSS importing code from my project into your ServerModule.
  • If you are using standalone deployment copy the dynamic manifest generation function from my project into your MainModule and insert the scrip-handling calls in your LoginForm or MainForm.

Something to be aware of regarding installing you PWA’s on your test device:

Chrome uses the URL as a unique identifier for each PWA. So once you have installed an app running on https://localhost:8077 you won’t be able to install another app running on the same port. So you have to either un-install the previous one or use a different port.

That’s it guys. I hope this post generates a bit of renewed enthusiasm.

 

PWA-VideoDemo.zip

  • Like 9
  • Thanks 4
Link to comment
Share on other sites

Really thanks... I have done a Lot of research on this subject. And as Far as I can see, nailed in all aspects.

But I think a solid solution should come from unigui team and/or Embarcadero because we are something like 5 years behind.

I Just cant ser How to keep update when delphi-unigui users are still amazed by bootstrap buttons and labels and layout issues or responsivity at devices ui/ux.

  • Upvote 2
Link to comment
Share on other sites

I have just been informed that the demo pwa project I uploaded does not run after installing on iPhone. The required correction is to change the  manifest.json as follows:

"start_url": "/"

I have also corrected the manifest belonging to this url and it should now work. https://www.qssldtf.com:8086 . You may need to uninstall and re-install.

So to all those who have downloaded the project, please change the manifest as per above. It should then install and run on all devices.

 

 

  • Like 1
Link to comment
Share on other sites

Keep in mind that PWA is not in the best interest of Apple ecosystem. 
There are some post in the web showing some trick for PWA in iPHONE.

Hence, google have two alternative for the future of webapps. Not even mentioning webassembly. I have no info in deep about it.

My last research on iPHONE / iOS subject was a "little" broken, to say the least.

Link to comment
Share on other sites

  • 1 year later...
  • 9 months later...
1 hour ago, wapps said:

The ZIP link is broken again. Can it be reuploaded ?

Hello,

The attached file is available for download.

 

Which edition and build of uniGUI are you using?

 

Link to comment
Share on other sites

Thanks,

Currently using TMS web core but looking into Unigui but PWA are an absolute necessity, so no subscription yet.

I hoped to be able to check whether it would work by using the trial edition before proceeding.

Link to comment
Share on other sites

2 hours ago, LOGISTICASOFT said:

The ZIP link is broken again. Can it be reuploaded ? 

Hello,

Let me remind you again that the link works and it is available to subscribers.

Link to comment
Share on other sites

8 hours ago, Sherzod said:

Hello,

Let me remind you again that the link works and it is available to subscribers.

Good morning, my email is RAMIREZ.CARLOS@YAHOO.COM, the last purchase I made was Nov2023 , I would not be able to say if there is any problem with my registration thank you

Link to comment
Share on other sites

  • Administrators
On 3/14/2024 at 4:10 PM, LOGISTICASOFT said:

Good morning, my email is RAMIREZ.CARLOS@YAHOO.COM, the last purchase I made was Nov2023 , I would not be able to say if there is any problem with my registration thank you

I fixed your forum membership status. Problem here was that your "forum email" settings was different than your main email.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...