December Adventure Day 07
Death by a Thousand Cuts
Keen to preserve the momentum from day 6 of my December Adventure, I decided to continue working on OpoLua—I’d really like to ship version 2 before the month is over.
OpoLua 2.0
While it doesn’t make for the most exciting write-up, I pressed on, polishing the Psion Software Index browser, and ironing out all the little wrinkles introduced by iOS 26 and the new SDK. For the curious, I’ve detailed some of the changes in the following sections.
Improved Library Management
With the introduction of the Software Index browser, there are now three different ways to get software into OpoLua: adding a folder to the sidebar, opening a standalone SIS (installer) file, and downloading a program from the Software Index. To try to better differentiate these flows, I switched to a plus-badged folder symbol for adding folders to the library, and moved the installer and Software Index flows to a menu in the main programs view. My hope is that by associating the actions with particular views, users will have an improved context for understanding the operations.
The Library view now boasts an add folder button
Tapping the plus button in programs views shows an install menu
Software Index Browser
Thankfully I’d already implemented most of the Software Index browser as part of the work to add it to Reconnect, my modern Psion plptools-based connectivity suite for macOS. This left a few remaining tasks:
- showing a spinner during initial load
- showing a progress indicator (spinner) when downloading programs
- displaying program hashes (used to differentiate between multiple builds with the same version) using a monospaced font
These proved relatively simple, with the exception of using a monospaced font, which necessitated a custom View extension as the .monospaced modifier isn’t available prior to iOS 16 (OpoLua targets iOS 15):
struct Monospaced: ViewModifier {
@Environment(\.font) var font
func body(content: Content) -> some View {
if #available(macOS 13.0, iOS 16.0, *) {
return content
.monospaced()
} else {
return content
.font((font ?? .body).monospaced())
}
}
}
extension View {
func monospacedCompat() -> some View {
return modifier(Monospaced())
}
}
Silkscreen Buttons
I updated the corner radii of the in-program soft silkscreen buttons—it turns out these were picking up the new metrics on iOS 26 and clipping the symbols.
iOS 26 wants to round absolutely everything
Dismiss Buttons
iOS 26 has all-but entirely moved away from buttons with text: ‘Done’, ‘Save’, and ‘Cancel’ buttons have all been replaced by xmarks and checkmarks. Unfortunately folks using older versions of iOS still (rightly) expect the older behaviour, necessitating conditional code like this:
ToolbarItem(placement: .confirmationAction) {
Button {
dismiss()
} label: {
if #available(iOS 26, *) {
Image(systemName: "xmark")
} else {
Text("Done")
}
}
}
The Settings, Installer, and Software Index views all needed updating in subtly different ways as we use a combination of UIKit and SwiftUI depending on the specific needs of each view and view controller.
The Settings view boasting a new symbolic dismiss button
While this kind of seemingly simple design language should make things easier, selecting the correct symbol and button type continues to require altogether too much deliberation: platform-provided semantic confirmation buttons on iOS 26 use a checkmark and are tinted making them far too prominent for most scenarios, often forcing me to override the platform defaults.
Swipe Actions
Continuing with the trend of replacing text with icons, swipe actions now use symbols, and the swipe action for removing library folders needed updating accordingly.
Nothing is safe from the iOS 26 redesign
With all these changes in place, I’m left with perhaps another day of things to do before I can submit to the App Store:
- the Installer ‘action’ buttons have the wrong radii on iOS 26
- the Software Index should only show OPL programs
- the new iOS 26 dismiss gesture steals drags from the running OPL program
- macOS and iPadOS need testing
Days like this are hard: I always find this process of adopting new Apple SDKs and UIs incredibly gruelling—a constant process of firefighting and decision fatigue that leaves me with very little room to apply the kind of slow, considered design I’d like to bring to my apps. I find myself uncertain of my own work, wondering if I need to look to other platforms in the future.
That said, I’m excited to be moving towards shipping OpoLua. If you’d like to try out the latest TestFlight build, please drop me an email at support@opolua.org.
Organiser II Software
Seeking a moment of respite, I looked into trying out a few more games on my Organsier II, only to find that many need to be written to ROMs to work. As I’ve only a single 64k datapak, I immediately found myself on eBay looking for some, and possibly nerd-sniped myself into building modern storage solutions. Pursuits for another day…