Splitter bars in React

I went through a load of splitter bar implementations for use within a React site, i.e. I simply wanted to partition my application into two halves (top and bottom), with a horizontal splitter bar.

The top half should be filled with a grid of data (I was using ag-grid), the bottom half filled with the query builder control. Also the button half should be capable of being collapse/hidden.

I was surprised at how hard it was to find anything that “just worked”. But this one did…

Run

yarn add m-react-splitters

Mine is “m-react-splitters”: “^1.2.0”. Now import the following

import Splitter from "m-react-splitters";
import "m-react-splitters/lib/splitters.css";

and here’s the basics for the code (obviously replacing the comment blocks with your components).

<Splitter
   position="horizontal"
   maximizedPrimaryPane={!showQueryBuilder}>
<div style={{width: "100%, height: "100%" }}>
<!-- grid -->
</div>
<div style={{width: "100%, height: "100%", overflow: "auto" }}>
<!-- query builder -->
</div>

Material UI in Xamarin Forms

To get nice, material ui, visuals on your Android and/or iOS application you can use the Xamarin.Forms.Visual.Material nuget package, see Xamarin.Forms Material Visual for a full explanation of using this package. I’m just going to summarise this information in this post for my own information.

Add the nuget package Xamarin.Forms.Visual.Material you may need to upgrade your Xamarin Forms if it’s an older version.

Init the FormsMaterial in the AppDelegate of the iOS project

global::Xamarin.Forms.Forms.Init();
global::Xamarin.Forms.FormsMaterial.Init();

and the same in the MainActivity

global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
global::Xamarin.Forms.FormsMaterial.Init(this, savedInstanceState);

Finally set the Visual element of the ContentPage, i.e.

<ContentPage Visual="Material"
/>

That’s all there is to it.

Sideloading an Android application from a website

You might want to supply your Android application outside of the Play store. This might be for testing or simply because you don’t want or need your application to go through the Play store (i.e. a bespoke application for a company).

Assuming you’ve got your APK file you can simply drop in onto a web site and link to it (or supply the location). For example

<html>
  <head>
    <title>My Android Application</title>
  </head>
  <body>
      <p>
      <h2>Install My Android application by clicking on 
this <a href="com.puridparrot.myapp.apk">link</a>
      </h2>
    </p>
  </body>
</html>

Simple enough – we might need to set the mime type, for example here’s the web.config for IIS

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <mimeMap 
         fileExtension=".apk" 
         mimeType="application/vnd.android.package-archive" />
    </staticContent>
  </system.webServer>
</configuration>

Now when you click this link from your device it’ll download the file and install it, you will need to set “Unknown sources” on to allow this to happen.

The downsides of this approach are that you obviously don’t get any notifications for updates to an application, also you’ll get a couple of security prompts to remind the user that this app. may not be from a trusted source.

Emailing (using default Email client) from mobile using Xamarin

A simply way to send email from Android and iOS using Xamarin is by using the Xamarin.Essentials.Email class. This allows us to use the default email client on the device to send our email, so we simply compose the email then pass the user to the default client to press the send button. What’s useful about this is our application can then leave the user to add any further information to the email without having to create the entry fields in our app.

You’ll need to add the NuGet package Xamarin.Essentials, then we can use the following code (don’t forget to add using Xamarin.Essentials)

try
{
   var message = new EmailMessage
   {
      Subject = subject,
      Body = body,
      To = recipients,
      Cc = ccRecipients,
      Bcc = bccRecipients,
      BodyFormat = EmailBodyFormat.PlainText
   };

   if (attachments != null && attachments.Count > 0)
   {
      attachments.ForEach(attachment =>
      {
         message.Attachments.Add(new EmailAttachment(attachment));
      });
   }

   await Email.ComposeAsync(message);
}
catch (Exception ex)
{
   // Log exception
}

On Android this will display the default email client, for example gmail, with all the fields filled in along with any attachments.

Express server and compression

You may want to turn on compression within your express service(s) in which case simply run

yarn add compression

and we just need to add to our server code like this

import express from "express";
import compression from "compression";
 
const app = express();
const server = http.createServer(app);
 
app.use(compression());
 
const port = 4000;
server.listen(port, 
  () => console.log(`Server on port ${port}`)
);

Now, in many case you’ll possibly already have the client header including the following

Accept-Encoding: gzip, compress, br

or you can set the headers yourself and express will serve up gzip compressed responses.

Remember though, that compression happens based upon reading an amount of data before starting to stream/send the response, so small(ish) amounts of data will not benefit from any performance increases, whereas large amounts of data will by the very nature of compression, reduce the amount of data being transferred and therefore you should see a performance increase.

See also Compression in HTTP.

Express server and cors

If we need to handle CORS within Express, we can simply write the following (we’ll assume you’ve also added express to your packages)

  • yarn add cors

Now our usual Express code with the addition of CORS support

import express from "express";
import cors from "cors";

const app = express();
const server = http.createServer(app);

app.use(cors());

const port = 4000;
server.listen(port, 
  () => console.log(`Server on port ${port}`)
);

Checking for known vulnerabilities in our node packages etc. with retire.js

I noticed, a while back, how github has some fabulous tooling which runs across our repos. on our maven and node packages (and probably more). I wanted to have something similar hooked into my CI/CD pipeline for my React and Node projects.

There’s several solutions, but the one I am talking about here is retire.js. There’s several ways to run retire.js, I’m going to concentrate on running it from the command line.

So first off you need to install retire.js, either globally or in my case I’m going to add to the dev packages

  • yarn add -D retire

You may also need to run the following if you get an error saying it’s missing

  • yarn add -D regexp-tree

Now we can simply run yarn retire from our project’s folder. Without any arguments this will run both JavaScript and NPM checks.

In my case I got three vulnerabilities listed for jquery, but as they’re primarily used as part of webpack dev server (in my case) I don’t really need/want them reported as they’re outside of my hands and hopefully webpack server will update them in forthcoming releases, so I want to ignore these for now. To ignore such reports create a file named .retireignore.json (other variants exists of this file), now add the following

[
  {
    "component": "jquery",
    "justification": "Used by webpack dev server"
  }
]

In this example I’ve ignored all issues around jquery, but that may be too course and mean we do not catch other possible issues around jquery usage, so we can instead add identifiers and list specific issues to ignore, for example

[
  {
    "component": "jquery",
    "identifiers": { "issue": "2432" },
    "justification": "CORS issue, we only worth within the intranet"
  }
]

Note: from what I could tell (although not 100% on this) you can only ignore single issues, even though the use of the plural “identifiers”. I would assume if you’re going to ignore multiple issues then it’s probable you would just ignore all issues for a specific version of a package.

We can ignore specific versions of packages using

[
  {
    "component": "jquery",
    "version": "3.3.1",
    "justification": "Used by webpack dev server"
  }
]

Pre-commit linting with husky and lint-staged

You’ve got your JavaScript or TypeScript project, you’ve added eslint and set-up all the rules and you’re happily coding, committing and pushing changes to GIT, the only problem is you’re ignoring your lint results or worse still, not even running lint prior to committing changes.

Enter, Husky and link-staged.

Note: I’m describing using Husky on a Windows machine, installation may vary depending on OS.

Let’s add them to our project using

  • yarn add -D husky lint-staged

Now, within package.json (after the scripts section is as good a place as any) add the following

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,jsx,ts,tsx}": [
    "eslint"
  ],
  "*.{js,jsx,ts,tsx,json}": [
    "prettier --write",
    "git add"
  ]
},

Note: Husky also supports it’s own configuration files .huskyrc, .huskyrc.json or .huskyrc.js

Husky adds the ability to run applications/code on various GIT hooks. The most useful, from the perspective of this post, is the pre-commit hook as we want to stop any commits until all lint failures are fixed.

In the configuration, above, we call lint-staged when GIT commit is executed. The commit hook will run husky and husky will then run lint-staged with the previously defined configuration.

Lint-staged runs the linter (in this configuration, eslint) over our various staged files and also executes prettier against the same files (as well as JSON) adding these changes.

With these two tools set-up, we no longer have the option to forget to run the linter or ignore it as it’s now part of the commit process. Ofcourse we only fail a commit on staged files, so in situations where we add these applications to an existing project we’re not force to fix all linting issues until we attempt to actually stage and commit the files.

I’ve merged or rebased and don’t want to fix everything

Obviously all’s great until you find old code that may need to be merged or we rebase and now have staged files which fail the lint process and we don’t want to fix them.

In such cases, simple set the environment variable HUSKY_SKIP_HOOKS to true or 1 prior to running a git command, for example

HUSKY_SKIP_HOOKS=1 git rebase ...

See Skip all hooks (rebase).

Beware the formatting infinite fix then fail circle

One thing to be aware of, if you’re using prettier, as per the configuration above, make sure your eslint and prettier adhere to the same rules – initially I found that eslint would complain about some formatting (I cannot recall which at the moment) so would fail the commit, upon changing the offending code to pass eslint, the prettier command ran as part of lint-staged and changed the format back, meaning it then failed the lint and would fail the commit again.

However, running prettier and having it write changes in obviously a great way to (at least try) to enforce consistency on our code format.

Requesting permissions in Android with a Target SDK Version >= 23

Various Android permissions (classed as “dangerous”), within applications targeting Android SDK >= 23 now require “requesting”.

So for example, on older Android versions we simply set the permissions, such as those for accessing Bluetooth, within the AndroidManifest.xml (or via the editor within Visual Studio – I’m using Xamarin Forms for my application, hence Visual Studio). These look like this

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

All works fine until you try to run your application (which requires these permissions) on an Android device with a >= 23 version. Instead, within the debug output you’ll see Security Exceptions around such permissions.

So along with our manifest, we now need to request these permissions within the MainActivity.cs we can write something like

private void CheckPermissions()
{
   ActivityCompat.RequestPermissions(this, new []
   {
      Manifest.Permission.AccessCoarseLocation,
      Manifest.Permission.AccessFineLocation,
      Manifest.Permission.Bluetooth,
      Manifest.Permission.BluetoothAdmin
   }, 1);
}

We might wish to first check whether a permission has already been granted, using code such as

if (ContextCompat.CheckSelfPermission(
   this, Manifest.Permission.AccessCoarseLocation) 
   != Permission.Granted)
{
   // request permission
}

On top of this, we probably want to either inform the user or handle failures to get the requested permissions (for example disabling such functionality), in such cases we override the OnRequestPermissionsResult method within the MainActivity.cs file (i.e. within the FormsAppCompatActivity class)

public override void OnRequestPermissionsResult(
   int requestCode, 
   string[] permissions, 
   Permission[] grantResults)
{
   // we may want to handle failure to get the permissions we require
   // we should handle here, otherwise call the base method
   base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

See Permissions In Xamarin.Android, also see the Android documentation Permissions Overview.