Mouse support in iPadOS/iOS13 Public Beta 3

The latest beta version of iOS13/iPadOS was released yesterday evening and I gave it a quick test this morning to see how the mouse support was coming along.

I know form comments made elsewhere that mouse support is not for everyone and some don’t understand why it is even necessary. For me it is a useful tool for when working away from my desk as I find it speeds up my work and make it a more pleasant experience. I still don’t think I could ever use the iPad as a permanent desktop replacement but it is a lot more usable than it once was.

In the video below I am using this TeckNet Bluetooth Mouse which at £10 is a lot cheaper than some others that have been suggested online. Several have sung the praises of the Citrix X1 but at £95 that’s more than I would want to spend on a mouse!

So here’s a quick video looking at the improving mouse support in the latest released beta version of iOS13 on an iPad. What works and what does not…

Have you installed the beta on your device? How are you finding the mouse support?

Using Google Translate to Automatically Translate a Symfony Language File

Recently the company I work for launched a new version of our product with multi-language capabilities. This was great for us but when we wanted to expand out to other languages we found that it was expensive to have the file translated.

Given that our language file is in a standard format (Symfony’s message YML format) we wondered if it would be possible to convert the file automatically via Google Translate and then give it to a translator to polish. It turns out that it is and this is quicker and cheaper than having all the file translated straight from English by a translator.

The routine itself is pretty straightforward but does require some set up beforehand. This includes creating a Google developer account, installation of Composer and the Google Translate API. All of this is described in detail with a step-by-step guide here.

I am going to assume that you have done all the necessary set-up. One important thing to remember is to setup you credentials on your machine for me (on a Mac but should be the same on Linux) you need to do the following:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/file/YOUR-GOOGLE-PROJECT.json"

The routine itself is written in PHP and runs from the command line and takes three parameters as follows:

  • name of the file you want translated
  • name of the output file
  • ISO code of the language you want to translate to (see here for list of supported languages)

So you might run it as follows:

php ./trans.php messages.en.yml messages.es.yml es

So here is the code, remember to change line 29 to include your Google project ID.

<php

// grab the file to be translated
if (empty($argv[1])) {
  die('You must give an input file'.PHP_EOL);
}else{
  $in = $argv[1];
}

// grab the file it is to be written to
if (empty($argv[2])) {
  die('You must give an output file'.PHP_EOL);
}else{
  $out = $argv[2];
}

// grab the target language
if (empty($argv[3])) {
  die('You must give a target language'.PHP_EOL);
}else{
  $targetLanguage = $argv[3];
}

require __DIR__ . '/vendor/autoload.php';

use Google\Cloud\Translate\TranslateClient;

$translate = new TranslateClient([
    'projectId' => 'YOUR-GOOGLE-PROJECT-ID'
]);
// open the input file to an array
$messages = file($in);

// create the output file
$translated = fopen($out, 'w');

// process each message
for ($i = 0; $i < count($messages); $i++) {

  // does this have any message text?
  if (strpos($messages[$i], ": ") !== FALSE){
    // translate the text
    $text = substr($messages[$i], strpos($messages[$i], ": ")+3,(strlen($messages[$i])-(strpos($messages[$i], ": "))-6));

    $result = $translate->translate($text, [
      'target' => $targetLanguage,
    ]);

    // write the translated line
    fwrite($translated, substr($messages[$i], 0, strpos($messages[$i], ": ")).": '".html_entity_decode($result)."'".PHP_EOL);
  }else{
    // rewrite the line
    fwrite($translated, $messages[$i]);
  }
}

// close the output file
fclose($translated);

echo 'Translated '.$i.' lines';

?>

In action it takes just a few minutes to translate the 1,000 or so stings we have in our language file.

Automatically Translate a Symfony Language in action

There would be a cost associated with this but I am currently using the free credits that I got when I created my Google account. Even so the costs are going to be tiny compared to having someone translate the whole file.

I am sure that there are ways that this could be improved but should prove useful as a starting point when you want a quick way to get a Symfony messages file translated.

iPad Pro, iOS13 and USB-c Dongles

Each year, regular as clockwork, Apple releases a new version of their operating system for mobile devices – iOS. This years version, iOS13, has recently been release for public beta and I took the plunge and installed it on my iPad Pro so you don’t have to!

Can’t we all run the beta?

Before we get too much into the new features of iOS here are a couple of reasons why you might not want to be installing it on your main device just yet. Beta software by definition is not fully baked and still has a number of bugs in it. The idea of releasing a public beta is so that Apple can get some valuable feedback and fix the major issues before go live to the masses, likely some time in October.

That means that if you are testing the beta version you will find issues and oddities such as the following…

Vertical toolbar on landscape screen anyone?

And this less that useful on-screen keyboard…

More icons

Probably the most visible change is to the home screen and the size of the icons which have shrunk. This allows for a greater number to be shown at once and has also allowed for a couple of widgets to be shown on the left hand side in landscape mode.

While this is fine as far as it goes when you have all slots filled (that’s 30 icons + another 11 on the toolbar) it does become increasingly difficult to find exactly what you are looking for!

Dark Mode

Since the introduction of the OLED screen on the iPhone X people seem to have been clamouring for a native dark mode on iOS and here it is.

Options are as you would expect with the ability to have it come on automatically at sunset and off again at sunrise or you can set your own schedule. Or turn it off completely.

For this to be of real use we will have to wait until apps on the app store are launch to take advantage of this.

Hubs

One of the reasons I upgraded to the beta was for the support of external storage such as SD cards, usb sticks and even hard drives. You can now plug in, via a cable or hub if you don’t have a USB-C drive, storage and finally manage it from the Files app.

What’s great about this is that with a USB-C hub you can plug in multiple devices at the same time and as long as they don’t use too much power all will work simultaneously. All storage appears as a separate section in the Files app.

This will be useful to be able to carry more media such as videos around without having to clog up the memory on the iPad itself and for transferring files.

Mice

Another nifty feature is the ability to support a mouse. Or at least it would be if I could get it to work. In theory both wired and bluetooth mice are supported but, to date, I can only get an old Logitech mouse to work. The Microsoft mouse connects be refuses to work unless the wired mouse is also connected. Of course this could be a beta issue that’s rectified in a later release.

The mouse support does work well though even if it does take a little getting used to. You can map the buttons onto a variety of actions such as opening the home screen. Scrolling also works but in the opposite direction to what I have set on my Mac so I hope that an option will be added to swap this in future.

I have read a number of posts online with people saying things like “wE doNT nE3D moUsE SuPpOrT” (literally like that!). For many that’s probably true but sometimes it makes no sense to be prodding the screen all the time and it is more natural to use a mouse. Having only the wired mouse doesn’t really work for me but if my Microsoft Bluetooth Notebook Mouse 5000 can be coaxed into life then I would be much more onboard with it.

Oh and one more thing…

It is no longer iOS on the iPad but iPadOS reflecting all the extras that it brings.

iPadOS has lots of other changes but they are covered just as well elsewhere. Are you going to load up the beta on your devices?

Text Expansion with Alfred

I’ve had my MacBook Air for over five years now and by and large it is still performing pretty well. Certainly better after that time than any Windows machines I’ve had in the past would have done.

Just recently, though, I’d been having a performance problem which led me to do a root and branch check of my machine (turned out it was the Sophos Home Virus scanner). As part of this I stumbled upon the fact that Alfred can do text expansion and this left me to wonder whether it was worth having two programs sat in the background waiting to do the same thing.

For years now I have used TextExpander for my text expansion needs and found it indispensable using it many times each day. But like so many others the company behind the program have moved to a subscription model and I am trying to wean myself off having lots of little subscriptions (I think that might be a post for another day). It’s not that I don’t value the program, I absolutely do, but I just am not a power user and so didn’t feel I’d be getting the value from the subscription.

That Alfred can do text expansion was, as I said, a bit of a surprise. I know it is very capable and again I use it all day every day but I did wonder what load was being added to my machine having two programs just sitting there looking at my keyboard input waiting for my to type my snippet keyword.

I have a reasonable number of snippets and didn’t relish entering them all again. Fortunately someone has written a routine to convert TextExpander snippets to Alfred format so testing it out was easy.

And how does it compare? I can safely say that I haven’t noticed any difference at all. So that was goodbye TextExpander. If you have both I would highly recommend taking a look and see if the switch might work for you too.

photofeeler – do I look good on this?

Everyone knows that looking good in your social media profile pictures is important and nowhere more so than on LinkedIn. But how do you know what is the best picture to use? Well that is where online service photofeeler comes in.

Photofeeler attempts to take some of the guesswork out of selecting the optimum picture by crowdsourcing views on pictures you upload aggregating the responses to give you a score.

You start by uploading a picture that you are interested in and select a category that this would be used with, so business or social. This is then available to other users to score on three attributes depending on the category. On the free account you can only have one test running at any one time and the responses are throttled so if you want quicker answers you’ll have to pay up.

After a few days you will start to see some results come through which look like the following. Here I have shown my current and previous LinkedIn profile pictures for comparison. I score more highly on the current one which is good!

The respondents also have the ability to add notes to go along with their score. Examples of these you can see below. If you think that they look a bit repetitive that’s because photofeeler suggests a list of notes you might like to choose from. Where people have taken the time and trouble to make their own comment it seems my shirt comes in for a bit of stick but hey I like it so I’m keeping it.

Does all this really matter you might ask. Well, according to LinkedIn, just having a photo “results in up to 21x more profile views and 9x more connection requests” so yes and having something that is appealing to people make sense.

Photofeeler makes sense for those that can’t work out what would be appropriate for their profile pictures and why what you use on LinkedIn might not be suitable for your Tinder profile. Judging by the number of dodgy holiday snaps I see on LinkedIn there are plenty that could make use of it.

Using the iPad Mini as a Kindle Replacement

I like reading and for years I have been happily doing so on a very old Amazon Kindle which was a hand-me-down from the wife. I never bothered to upgrade as the newer models always seemed bulkier than what I had.

That was until like everyone else on the planet when you reach a certain age you need glasses and things become difficult to see, particularly in low light. My existing Kindle had no light and so I was forced to start thinking about a replacement.

Initially I toyed with the idea of a new Kindle or more likely my wife getting a new Kindle and me getting her old backlit model. But I am all in on Apple and so I wondered if an iPad Mini might not be a suitable alternative. So I picked up a generation 1 16gb model off eBay in order to find out and this is what I thought.

The first shocker was that it could only run iOS9 which meant it felt slow and the latest Kindle app isn’t compatible! Fortunately as I had previously downloaded it I offered the chance to download a previous version which works just fine. Phew!

Next issue was that the glass screen is highly reflective and it was almost impossible to see anything due to the light. After a quick bit of research I found these anti-glare screen protectors which are brilliant. Not only have they completed eliminated the glare but it also give the screen a very similar feel to the Kindle.

With the hardware side of things out the way I was finally able to read a book! Unsurprisingly this is very similar experience to my previous Kindle with the bonuses of it being lit and colour which means you can change the paper type for example.

That it’s colour also means that it is great for graphical content such as comic books and it is here where the iPad scores highly over the Kindle. As it is running iOS you can download anything from the app store (albeit with the iOS9 compatible restriction). So I have installed Comic Zeal and Instapaper and, of course, Safari so you have the whole of the web too.

Another plus is the Audible integration. If you are not familiar with Audible it is Amazon’s audiobook arm, an area growing quicker than ebooks. What’s neat about this is that your progress is synchronised between the ebook and audiobook (assuming that you own both). You can download the audiobook in the Kindle app and listen or read.

Of course the battery life on the iPad is worse than the Kindle but nowhere near as bad as I expected it to be. Just using it as an ereader gives me days worth of use without worrying about recharging. Of course as it is charger from a lightning cable I have lots of those around so there is always one to hand.

All in all I am happy with the switch and would recommend it for anyone that wants a colour, multi-talented ereader.

Pros

  • Works well
  • Can read at night
  • Can be used for other things
  • Colour screen so better for graphic content
  • Better synchronisation between kindle apps and devices
  • Audible

Cons

  • Screen very bright and needs an anti glare cover
  • How long is the software going to continue to be supported? 
  • Very slow!
  • Battery life not as good. Charge more frequently.

Sending today’s PipeDrive activities to Remember the Milk

Until very recently Google used to allow you to forward an email based on a filter. So you could receive an email see that it was from x and then automatically forward it on to y. This was beneficial and I used it to send the today’s activity notifications from our CRM (PipeDrive) to my task manager (Remember the Milk). Now Google has ceased this functionality on privacy grounds.

With this feature gone I could no longer see my activities in Remember the Milk (RTM) which was a pain. So I wrote a little script that used the PipeDrive api to find all my activities for today and send them to RTM where a task is created. For this part I used the RTM email in facility that allows you to email a special address and get a task created.

I thought that it might be useful for others to see how this was done so the code is below. It needs PHPMailer to send the email in this example but you could swap that out for something else. I’ve broken it down into several chunks to aid readability.

You will need your PipeDrive user ID which you can get by going to your detail page and then look for the number at the end of the web address as shown below;

First off set some constants used later on. You will need to change these to your own details.

// Your PipeDrive details
define('PIPEDRIVE_API_URL', 'your PipeDrive api url here');
define('PIPEDRIVE_API_KEY', 'your PipeDrive api key here');
define('PIPEDRIVE_USER_ID', 'the unique number of your PipeDrive user');
// RTM details here: https://www.rememberthemilk.com/services/email/
define('RTM_EMAIL_ADDRESS', 'the email address to email in to RTM');
// SMTP details
define('SMTP_HOST', 'address of your SMTP server');
define('SMTP_PORT', 'port of your SMTP server');
define('SMTP_USERNAME', 'email account username');
define('SMTP_PASSWORD', 'email account password');
define('SMTP_EMAIL', 'your email address');
define('SMTP_NAME', 'your name');

Next request from the PipeDrive API all the activities that are due today.

 
// get all activities for selected user
// Details here: https://developers.pipedrive.com/docs/api/v1/#!/Activities/get_activities
$ch = curl_init();
$request = PIPEDRIVE_API_URL."/activities?user_id=".PIPEDRIVE_USER_ID"&start=0&done=0&api_token=".PIPEDRIVE_API_KEY;
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($ch);
$response = json_decode($curl_response, true);
curl_close($ch);

Then cycle through any that have been returned extracting the details you need. I have chosen the name and their organisation but you can check the api reference here for what else is returned.

 $activities = '';
 for ($i = 0; $i < count($response['data']); $i++){
   if ($response['data'][$i]['due_date'] == date('Y-m-d')) {
    $activities .= ucfirst($response['data'][$i]['type']).' '.$response['data'][$i]['person_name'].' ('.$response['data'][$i]['org_name'].')'.PHP_EOL.PHP_EOL;
  }
}

We now have a formatted string containing a list of people and their organisations, one per line, that have activities due today. The final step is to send the email.

The most important bit here is the subject line which uses RTM’s Smart Add syntax so you will need to change this to reflect the list you want the task to go to and anything else. At present it will create a task called “Pipedrive activities” with a priority of 1 for today. The activities details appear as a note appended to the task itself.

if ($activities != '') {
  $mail = new PHPMailer();
  $mail->IsSMTP(true); // SMTP
  $mail->SMTPAuth   = true;  // SMTP authentication
  $mail->Mailer = "smtp";
  $mail->isHTML(true);
  $mail->Host= SMTP_HOST; 
  $mail->Port = SMTP_PORT;
  $mail->Username = SMTP_USERNAME;
  $mail->Password = SMTP_PASSWORD;
  $mail->SetFrom(SMTP_EMAIL, "SMTP_NAME");
  $mail->AddReplyTo(SMTP_EMAIL, "SMTP_NAME");
  $mail->Subject = "Pipedrive activities !1 tod #list";
  $mail->MsgHTML($activities);
  $mail->AddAddress("RTM_EMAIL_ADDRESS");
  // send the email
  $mail->Send();
 } 

You’ll probably want to also schedule the task to run nightly so that they automatically appear in your task list each morning. I find it’s a good way to remind me of what’s needed for the day ahead.

Is this the world’s most expensive charger?

One of the disappointments of the new iPad Pro was that all those lightning charge cables and accessories that I’d accumulated over the years immediately became useless. However, the move to USB-C meant that the iPad had a bit of a trick up its sleeve – charging. As you can see from the image above here it is charging my Apple Watch.

The iPad Pro can charge accessories such as your watch, iPhone etc. at a 7.5W charge rate – providing that you have the right cables. To do so requires a potentially expensive outlay in new USB-C to lightning and watch charge cables – currently £50 if you buy the official Apple variants.

But does it work? Well, yes it does and the charge speed isn’t too shabby either for on-the-go charging. In the time it has taken me to type this post my watch has added another 25%.

It is a useful tool in the charging kitbag but I don’t think that it is going to completely replace the need for a mobile battery as I certainly can’t get my iPad Pro into my pocket, something I frequently do when needing to charge my iPhone on the go. That said it is a useful stop-gap and the huge battery in the iPad does mean that you can afford to sacrifice some charge from it in order to keep your other kit topped up.

Recording who clicks which link when on Sendy eMailer

For many, Mailchimp is a reliable mailer for sending newsletters and other automated email campaigns. And for some it might even be cost effective but unless you are sending very few emails I’d suggest not. Whatever your views on costs it is very easy. However, if you’re already using Amazon’s AWS then there are other services that, with a little effort, might well be cheaper. These take advantage of the fact that you get a generous free sending limit with your account.

Sendy is one such service which does much of what Mailchimp does. It can send nicely formatted emails in html and plain text, run multiple lists, help you to be GDPR compliant, manage unsubscribes and much more. If you are willing to go through the setup and, perhaps, host it yourself it is a good option.

While Sendy is feature packed it has always surprised me that it is missing something that I consider to be important – the ability to see when someone clicked a link. To be clear you can get a list of who clicks on a link in a campaign but you have no idea when. This makes any follow up actions, such as creating an activity record in your CRM for that time (which is what I needed to do) impossible. So I decided to try and fix this deficiency.

The issue, to my mind, is how Sendy stores the clicks. This is done as a comma separated list of subscriber IDs in a longtext column in the links table. The latest click of a link just sees the latest subscriber ID added to the end of the list. What I really needed was a table that held the individual clicks along with WHEN the person actually clicked. So I created a table for this:

 CREATE TABLE campaign_click (
    id INT NOT NULL AUTO_INCREMENT,
    subscriber_id INT NOT NULL,
    clicked_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    link_id INT,
    primary key (id) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Then I created a trigger that fires every time the links table is updated and the clicks column has changed:

DELIMITER #
CREATE TRIGGER tr_links AFTER UPDATE ON links
FOR EACH ROW
BEGIN
IF (old.clicks != new.clicks) THEN
INSERT INTO campaign_click(subscriber_id, link_id)
VALUES (SUBSTRING_INDEX(new.clicks, ',', -1), new.id);
END IF;
END#
DELIMITER ;

What this does is whenever the links table is updated and the click column has changed details of the click will be inserted into the campaign_click table. Bingo! We finally have a record of who click which link when.

Now you can do things such as list all subscribers that clicked a link in the last hour:

SELECT c.`clicked_at`, l.`link`, a.`title`, s.`email`
FROM `campaign_click` c, `links` l, .`ares_emails` a, `subscribers` s
WHERE c.`clicked_at` >= DATE_SUB(NOW(),INTERVAL 1 HOUR)
AND c.`link_id` = l.`id`
AND l.`ares_emails_id` = a.`id`
AND c.`subscriber_id` = s.`id`

You can make this more sophisticated should you require but you get the idea.

I should say that Ben, the author of Sendy, may well not approve of this hack and any update that is released in future may way overwrite this but I suspect that it will be ok. Use with caution, you have been warned!

Kablecard – The Swiss Army Utility Card for Charging on the go!

Kickstarter has been a bit hit and miss for me but occasionally it does turn up a real gem and Kablecard is one of those.

I have to say that when I saw the video and spec list (multi-head charging! sim tool! kick stand! back light! memory storage! credit card sized!) it did seem a bit unbelievable and I wondered if it was a scam. But no, I did end up with one and it really can do all the things that it claimed.

Inside the Kablecard

Included inside a quite thin case is a main cable which is USB-C at both ends. You can then change the tips of the cable with the included micro-USB, lightning and USB-A heads. As you will see from the video below this allows you to do things such as connect the USB-A and lightning heads and attach it to a battery to charge your iPhone. 

Tucked away to the side is also a microSD card slot which means you can whack a card in there and then connect it to you laptop for a bit of external storage. This might save you having to carry both the card and a USB stick but then who does that these days?

As you can see in the video it all works well but is a bit fiddly. My only gripe is the back plate is pretty thin and the hinge at the top only opens to the angle to allow it to work as a stand. This isn’t immediately obvious and would be possible to snap it off if you didn’t know.

However, all in all, it is a good addition to the kit bag and easy enough to slip into the pocket along with the AirPods ensuring you always have the right cable with you.