Week 10

    Doodles, UX, and COVID

    Just a week after returning to my weeknotes, it's going to be a lighter one this week as Sarah and I managed to catch COVID. I spent a little time on Builds, but also took a some time off work-like projects to play around with ideas for my thermal printer and continue the Little Luggable Raspberry Pi 5 upgrade.

    Builds

    The first half of the week was spent trying to get Builds ready for a first private TestFlight beta–I've had a few friends express interest and I'd like to let them try it out. (If you're also keen to test out an early beta, please get in touch.)

    Getting Started and Adding Workflows

    When I first started working on Builds, I was primarily interested in seeing if I could create something that improved my own daily development experience. As such, I put very little effort into the flow for adding GitHub Actions workflows to the app (a simple dropdown list was sufficient), instead focussing on the primary functionality of fetching and reporting statuses. Now that I'm planning to let others use the app, on-boarding becomes significantly more important.

    Builds reports on branch-specific runs of GitHub Actions workflows. This means that any on-boarding flow needs to make it easy for users to select, for each of their repositories, pairings of workflows and branches.

    Builds shows statuses for workflow runs on specific branches

    My initial implementation for adding workflows presented users with a view containing three pickers allowing them to select a repository, workflow, and branch:

    This proved slow and cumbersome, offering no overall context and making it easy to forget workflows or unintentionally add duplicates. It also translated incredibly poorly to iOS which offers no way to quickly navigate big pickers.

    Pickers don't scale well on iOS

    With these failures modes in mind, I set about designing something better:

    It's actually quite hard to break down the many thoughts and iterations that went into this but, while I'm sure there are still improvements to be had, I'm pretty pleased with how it's turned out. The main goal is to show users as much context as possible, making it quick to add and remove builds, and easy to see all available builds. Setting up the app from scratch multiple times during development has proven a great stress-test for this workflow and I'm happy with how it works.

    One challenge in designing the experience was figuring out what to do with the explosion of per-branch workflow runs. For example, if a repository has 3 workflows and 5 development branches, that's a possible of 15 workflow builds. After much experimentation, I've settled on showing workflow runs on only default branches by default and using a picker to allow users to add additional branches. This optimizes for the primary use-case where people are interested in understanding whether 'main' builds, but also accommodates projects with long running development or dedicated release branches.

    Syncing Settings with SwiftData, CloudKit, NSUbiquitousKeyValueStore

    Having decided I want to support both iOS and macOS, I put some time into thinking about the sync story–it's incredibly jarring to have the same app on multiple devices but have to configure each individually and I want to avoid that.

    I'd assumed my minimal needs would make this a perfect use-case for SwiftData but a lack of observer mechanisms outside of the SwiftUI lifecycle made it near-impossible to use for fetching statues in the background. I briefly explored using the CloudKit APIs directly but, in the end, settled on storing a simple array of workflow favorites in NSUbiquitousKeyValueStore–it seems good enough for my current lightweight needs and I can switch it out if I start to see syncing issues. I've been living on this implementation for about a week and it's been rock solid.

    Writeme

    Early on in the pandemic, when we were all encouraged to quarantine mail, I put together a Raspberry Pi powered receipt printer based on Adafruit's Internet of Things Printer. Press a button, and it would print out quarantine 'release' tickets to let us know when our mail could be opened. Since that time has passed, it's been sitting unused on the shelf and I've been dreaming up things to do with it.

    Spurred on by Dan Catt's pen plotter art–especially his recent work focused on handwriting–I thought it might be nice to use the receipt printer as a way to help manifest digital things in the real world and try to bring back a little whimsy in the process. With that in mind, I created Writeme.

    Writeme allows anyone to send a little doodle to my receipt printer. It's quite possible I'll come to regret this (gone are those heady early days when putting something like this on the Internet seemed like an unquestionably great idea), but hopefully it brings a little entertainment while it lasts.

    It's been fun to see what people have sent so far and I'm looking forward to a few more doodles.

    Little Luggable

    Just like last week, I spent a little time tweaking the Little Luggable.

    When I originally built the Little Luggable, I picked up the Pimoroni Audio Amp Shim with a view to driving a built-in speaker but never quite managed to get it working. At the time I was using Manjaro on my Pi 4 so thought the issue might have been with the drivers, and eventually gave up. Since I'm now Raspberry Pi OS on my Pi 5 (for the moment at least), it seemed like a good time to try again. Just like my experience with Manjaro, the Pi would list the device but didn't seem to be able to talk to it, with alsamixer complaining that it had 'no controls'. Having read around a little, it seemed like the issue might be with the shim's friction-fit connectors1 so I broke out the soldering iron. A few minutes later and I was enjoying the dulcet tones of a wilhelm scream at a loud 100% volume through MPlayer. Keen not to repeat that experience in a hurry, I broke out ScummVM and a few games instead.

    Enjoying a bit of Riven on the Little Luggable

    Much to my surprise the Little Luggable's mono speaker sounds quite good–far better than most laptops and monitors.


    1. Even the Pimoroni product page includes the comment, "[t]o ensure a robust connection, we'd suggest soldering the SHIM to your Pi's GPIO pins (or a socket header) when you come to install it in your final project". 

    Week 9

    Much Software

    Life is starting to look a little calmer, and I thought I'd try a return to my weeknotes.

    This week has involved lots of software (Symbolic. Folders, and Builds), a little bit of hardware (Little Luggable), and some retro operating system fun (Haiku). There are also a few honorable mentions.

    Symbolic

    I've spent the past couple of weeks trying to get Symbolic–my Apple developer-focused icon designer–ready for release. Things stagnated last year when I realized I couldn't legally sell the app through my UK company thanks to various US tax liabilities but, now I've finally got my US work authorization back again, I'd like to get it in the App Store.

    After much thought, I've decided to make Symbolic subscription-based: $0.99 a month, or $9.99 a year (at least to start with). This will be the first app I've ever sold, so it's quite an adventure for me; asking for money really doesn't come naturally. My goals with this are three-fold:

    1. encourage me to take my own projects more seriously

      While I aspire to making a living from my own creations, it's all too easy for me to trivialize my projects. I'd like to test the theory that it'll be a lot easier to take them seriously if proves that people are willing to pay money for them.

    2. start to cover some of my infrastructure costs

      Building software is an expensive business, both in terms of software and hardware infrastructure costs. Mine are currently unsustainable, so something's got to give.

    3. learn what others want from my software

      I'd really like to get input on what people like (and don't like) about Symbolic and my other apps. I've got some ideas about where to take things, but ultimately I'd like that to be guided by my users, and my gut feeling is that I'll get a different quality of engagement from paying users.

    Of course, part of my reticence in actually selling my software is the distinct possibility that no one's interested. I suspect Symbolic has a small target audience at best, but I'm hopeful I'll get a few users. If I don't, I've at least learned something. 🤞🏻

    Having decided to go with a subscription-based approach, this week has been focused on integrating StoreKit and testing all the edge-cases1. I'm currently planning on only requiring a subscription for exports, which should mean users can get a really good sense of what they're getting into before subscribing.

    Folders

    Folders is an app I've been tinkering with for a few months now–it's one step in what feels like a long journey of experimentation around producing a better device-local experience for managing my files. With Folders, I'm inching ever closer to a Photos-like experience; one that's already working better for me for the many multimedia files I've collected over the years.

    So far, my focus has been on building a live-updating file browser app that performs well regardless of the number of files I throw at it. That means SwiftUI is out for all but the most structural elements of the UI, and AppKit is in.

    Last week my work was primarily around the correctness of those live updates–Folders uses FSEventStream under the hood to watch for changes, and turning those events back into high-level file operations is nuanced. My goal is that Folders responds to on-disk changes as quickly as Finder and, after quite a bit of work, I think I'm finally there:

    It's been challenging to stay focused on the more fundamental aspects of Folders–now the app's taking shape, I'm starting to get excited about all the extra features I can add. I plan to take a little more time to sure up the foundations after which I'll start building some search indexes and really having fun!

    Builds

    Builds is a status board for GitHub Actions. Like Symbolic, it's an app I originally wrote to serve my own needs that has rapidly become a core part of my workflow, and is increasingly looking like something others might find useful. The premise is pretty simple–it shows tiles with the statuses of each of your GitHub Actions workflows.

    There's clearly a lot of room for feature creep with Builds, but right now I'm focused on reporting current build statuses concisely, and offering a consistent experience across iOS, macOS and iPadOS. With that in mind, this week's work has been on CloudKit sync which gave me a nice excuse to try out SwiftData for the first time.

    I've got grand plans to add some little desktop toys for reporting overall build status (maybe I can resurrect the integration cats), but I imagine it'll take a while before I can get to them.

    Little Luggable

    I finally managed to snag an 8GB Raspberry Pi 5 so I took a cursory look at updating the Little Luggable. The increased power demands of the Pi 5 make for a great excuse to rethink the battery situation–I'm planning to try out the Geekworm X1202 UPS HAT which I think I can squeeze into the Pelican Case with a little care, and which I hope will prove significantly more reliable than the PiJuice I've been using so far.

    Sadly I've not yet managed to test the Pi with the Little Luggable's touchscreen as the display cable pitch has changed. I've got one on order so hopefully I can do that next week.

    Inspired by progress updates on the MNT Pocket Reform, I've also been wondering about laser etching legends onto the Rama Works GRID keycaps–they look wonderfully minimal without legends, but aren't entirely practical.

    Haiku

    Spurred on by Action Retro's enthusiasm for all things Haiku, I revisited my goal of daily-driving Haiku on my ThinkPad T460. Things are, unfortunately, still a little shaky on actual hardware–I had to pick up a TP-Link USB WiFi adapter as the built-in Intel chipset didn't work–but it's getting there slowly and I managed to do research for the Little Luggable using just Haiku last night.

    Haiku is a charming operating system and after many years of macOS it's a pleasure to play around with different windowing and architectural approaches, even if they do come out of the 90s.

    Honorable Mentions

    Since I've not written many updates lately, there are a few things that have slipped through the cracks:

    • Tom and I shipped a minor update to OpoLua that adds better game controller support and a few runtime fixes.
    • Overview is now available in the Mac App Store.
    • I've been making good progress getting InContext to compile on Linux–I managed to build my Markdown-only Recipes website under Fedora which feels like a great start.

    1. Renewals are my current nemesis. 

    1Password and Hyprland

    I've recently been trying out the Hyprland on my Fedora-based ThinkPad. It's a breath of fresh air next to macOS, combining the fast functionality I've come to expect of a tiling window manager with good looks and elegant animations.

    One of the challenges I've found to be consistent across tiling window managers however, is how they handle apps like 1Password that offer more transient experiences. Since traditional window managers don't differentiate between tiled and more transient floating windows, you're left to add these annotations for yourself.

    Fortunately, Hyprland makes it easy to add window rules that instruct it to treat certain windows specially. For example, I use the following set of window rules:

    windowrulev2 = float, title:(1Password)
    windowrulev2 = size 70% 70%, title:(1Password)
    windowrulev2 = center, title:(1Password)
    

    This ensures that the 1Password window (specifically any window titled '1Password') will open centered, 70% of my screen size, and floating above all other windows, making it minimally disruptive when I unlock 1Password to log into a website.

    Checking a password no longer disrupts my window layout

    To round things out, I've also added a key-binding to let me quickly launch 1Password using Super+\, replicating the workflow I'm familiar with from macOS:

    bind = $mainMod, code:51, exec, 1password
    

Archive