At Dubai International Airport, buying $12 coffee and looking for departure boards, which are few and far between.

Inside the terminal of Dubai International Airport, looking at palm trees next to a travelator.

Oof. Hours away from departure and I almost forgot to organise travel insurance. Probably need to write up a checklist for future trips. Remarkable how much is not done for you when you’re not travelling for work. πŸ˜„

At the cafe this morning. The ledge of this cabinet is the perfect height for dogs to do this. I always enjoy seeing it.

Little dog reared up with front paws on a low ledge of a glass cabinet holding cakes.

It’s easy to forget that the Mac is capable of making pretty decent screencasts with just QuickTime Player. I’m using it right now to prepare handovers at work: recording how to deploy something to prod so that someone can take it on while I’m away. It’s super useful.

For anyone else that’s interested, the Pixel 6 Pro supports dual SIM, with one of them being an eSIM. Useful information for anyone wanting to buy a local SIM for a trip overseas. Would’ve saved me a bit in international roaming charges if I knew this last year, but better late than never.

One of those days where something’s broken and you’re looking into it, but you can’t because a thing you rely on is also broken and you’re waiting for that to be fixed. This is while you’re side-tracked looking at something else, which is also broken for reasons that are beyond you. 😩

I’m trying to be better at finding solutions to problems rather than just complain about them here. Just this morning I was going to complain about how I wish MacOS had per-mouse tracking speeds. Instead, I made a Keyboard Maestro macro to address this. If it works, I’ll write about that instead.

I’ve been working on Micropub Checkins over the last week. It’s been a bit of a rush trying to get it into a usable state for an upcoming trip. And by “usable”, I mean a form that I can tolerate, and when it comes to projects like this, I can tolerate quite a lot. It can have a really dodgy UI (which this does) and miss some really important features that are annoying to work around; but if it works, and doesn’t loose data, I’ll be fine with it.

The main screen showing three check-ins
The main screen showing the recent check-ins. Note the lock next to some of them. These won't be published until the locks are removed.

The last week was dedicated to making the act of checking in distinct from publishing it. Until now, check-ins were published the minute they were entered, meaning that you cannot check-in somewhere unless you’re comfortable with people knowing where you are the minute you do. Yes, some people like it that way, but not me. And I’m aware that this’ll only be the case if people are following my check-in blog, which I’m doubtful of.

So pressing the floating action button and choosing a check-in type now starts the flow of a new check-in that will get saved in an SQLite database. You can edit the check-in whenever you like, so long as it’s not published. Currently there’s no real way of deleting a check-in unless it’s been published. This is a bit dodgy, but it’s a good example of how tolerant I am with working around these feature gaps for the moment.

The new styled edit screen with a title, description, rating, and a ready for check-in switch
The newly styled edit screen. Notice the rating field, which will appear for eateries.

Check-ins can be published by tapping the upward facing button on the main screen. Any check-in with a lock is private and will not be published until you toggle the “Ready to publish” switch in the properties. Doing so will not change the date of the check-in: it will still have the date and time that check-in was created.

The target list screen, showing two targets: one test target, and one for my real check-in blog
The targets are currently hard-coded but they can be turned on or off. I had a bit of trouble publishing a check-in to two targets, so I'm not sure if I'll keep multi-target publishing.

On the subject of publishing, I had some issues with Dart’s date and time methods. The method on the DateTime class used to produce an ISO-8501 date-stamp don’t include the time-zone if the date and time is not in UTC. This is important as I want the post date and time to be as close to the check-in time as possible, and in the time-zone of the phone. DateTime knows all this, including what the time-zone we’re in. So why didn’t the developers include it in the ISO-8501 date-time string?

This is really strange. Fortunately, ChatGPT stepped in to help out, writing a function which will add the time-zone offset to the ISO-8501 date-time string:

String formatTimeZoneOffset(Duration offset) {
  String sign = offset.isNegative ? '-' : '+';
  int hours = offset.inHours.abs();
  int minutes = (offset.inMinutes.abs() % 60);

  return '$sign${_padZero(hours)}:${_padZero(minutes)}';
}

Honestly, ChatGPT has been so helpful over the past week with this project, I probably should give it a credit if I get this polished enough to release.

Turns out the reason behind my failed attempts at connecting to the VPN I was setting up yesterday was because another VPN running at the time was masking my external IP address. Completely forgot about that one. Turning it off has resolved the issue.

It’s wet and cold outside, and I’m currently sitting in cafe that’s got Christmas Carols playing for some reason. Interesting start for a Sunday.

Inside a cafe looking out the door to a wet pavement and grey scene

For anyone looking to waste a morning, may I suggest trying to set up and debug a VPN. Always super fun spending two hours on it and having nothing to show from it at the end. πŸ˜’

Only caught the last 15 minutes of the Micro.camp keynote with Om Malik. Looking forward to watching the whole thing on YouTube. It’s also nice to finish the community discussions, then start my regular Saturday. Kinda feels like I’m getting away with something. πŸ•οΈ

I think it’s time for the Go maintainers to add a UUID type to the Go standard library. Not so much for generating or parsing UUIDs β€” all the packages already out there do this quite well β€” but to have a standard API that other packages, like logging frameworks or database clients, can rely on. Right now these developers need make a choice of which third party UUID package they’re going to use. And if it’s different than the one you’re using, well… sad faces will occur.

Keeping a separate blog for journaling personal project work is becoming a bit of a hinderance. There’s always this uncertainty of where a post should go: it’s about my day but it’s about a side project but not really, so should it go here? Might be time to merge that blog into this one.

Update 21/5: I’ll keep them separate for the time being.

Full Width Notes In Obsidian

More custom styling of Obsidian today. This snippet turns off fixed-width display of notes, so that they can span the entire window. Useful if you’re dealing with a bunch of wide tables, as I am right now.

body {
    --file-line-width: 100%;
}

div.cm-sizer {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

I wish I could say credit goes to ChatGPT, but the answer it gave wasn’t completely correct (although it was close). The way I got this was by enabling the developer tools β€” which you can do from the View menu β€” and just going through the HTML DOM to find the relevant CSS class. I guess this means that this’ll break the minute Obsidian decides to change their class names, but I guess we’ll cross that bridge when we come to it.

I’ve become so cynical of online service that I’ve been finding myself going to the pricing page whenever I’m evaluating something new. If I can’t find one, I get suspicious of how they’re able to support the service. Even if they have no ill intent, they need to keep the lights on somehow.

Did some Flutter development last night. Dart is such a weird language. Usually it’s really boring, maybe even too boring. But then you encounter something just bizarre. Like, if you format a DateTime as ISO-8601, the time-zone offset will not be included if the time-zone is not UTC. So strange.

I don’t do a lot of front-end JavaScript development. When I do, I tend to go towards something super lightweight like Stimulus or try to avoid using a framework altogether. But after looking at Svelte, and trying it out to build something simple, I think I can grow to like it.

It kills me that Stripe offers six test cards that simulate errors when attaching to a customer, yet only one test card that simulates payment failures once it’s attached.

I got a little bored today so I added task progress indicators to this Obsidian roadmap thing I built for work.

Screenshot of coloured rectangles next to a link with the text 'View In Jira' and below the heading 'Jira Tickets'
What the task progress indicators look like.

When a task is created, but is not yet scheduled, it appears as an outlined rectangle. It turns into a grey rectangle when it’s added to the sprint. It then changes colour as the task progresses through the software lifecycle; turning purple while it’s being developed, blue while it’s being tested, and finally green when it’s ready for release.

They’re implemented as embedded SVG images, added directly to the note much like the span element used for status labels.

Screenshot of the markup of the embedded SVG image next to the 'View In Jira' link
Move the insertion point over the the SVG image to edit the markup.

It’s nice being able to add embellishments like this. Obsidian treating notes as regular files on the file-system is a huge advantage for these sorts of automations. No need to learn how to make a plugin; just write a shell script1 that’ll output Markdown, schedule it to run a couple of times a day, and you’re good to go.


  1. The “shell script” is actually written in Go, using the really useful script package to simplify all the pipelining stuff. ↩︎