Screenshots
-
This is still true to this day. ↩︎
- Micropub Checkin: A silly little Flutter app I used for adding check-ins to lmika.day. The apps in a bit of a neglected state, but I still use it as I get value from tracking places I’ve been.
- Strata: The note’s app from Micro.blog. This is where I write my short-term notes. I use Google Keep for shopping lists, but everything else goes here.
- Alto: A music app I wrote, and the main music app I listen to.
- Pocket Casts: The podcast player app I use. Apart from the web-browser, this and Alto are two of the most used apps I have on my phone.
- VSReader: Another silly little Flutter app. This is a test build for an RSS reader I was working on a couple of months ago. It’s been a while since I’ve opened this, and I probably should just kill it given that I haven’t made any recent changes to it.
- Google Wallet: Google’s digital wallet (well, at least their current iteration of their digital wallet). I use it mainly for my train ticket but I do have my credit card in there, just in case I walk out without my “real” wallet.
- Phone: My family and I still use the phone quite frequently so this app has remained in the dock since I set the phone up.
- Messages: This is Android’s messaging app. Much like the phone, I communicate with family mostly via SMS, and now RCS, messages.
- Play Store: I rarely go to the Play Store, so there’s no real need for this icon to be here. But I haven’t got around to removing it yet.
- Vivaldi: My web browser of choice.
- The right most icon changes based on the last used app, which I’m not a huge fan of, as it occasionally changes just as I go to tap it and I launch the wrong app by mistake.
- PTV: The Victorian public transport app. I usually use it to know the arrival time of the tram I take going home. Also useful for trip planning.
- Plex: I generally don’t watch things on my phone, but before I got my Nvidia Shield, I used this Plex app to Chromecast shows to the TV. It was never great at it though, as it sometimes disconnected from the Chromecast session while the video was running, leaving me with no means of stopping it until I unplugged the Chromecast.
- Kindle: Kept here as I occasionally use it to read books if I’ve read through my RSS feeds.
- ChatGPT: I don’t use ChatGPT on my phone that often, but it does occasionally come in useful when a web-search proves fruitless.
- FastMail: My email provider of choice. Given how often I use it, this is arguably one of those apps that should be on the first screen.
- Pager Duty: The twenty-four hours on-call paging software I had to use for work. I’m no longer on the on-call roster so it’s probably something I can remove.
- WhatsApp: What I use for messaging friends. I don’t like the fact that I have a Meta app on my phone, but that’s what my friends chose to use so I’m stuck with it (it’s also better than Viber, which is what we used before).
- WireGuard: Personal VPN, although I’m currently not using WireGuard for anything right now. I like to keep it mainly because I like the logo.
- Discord: I’m a member of a few Discord servers, but I use the mobile client mainly to check into the Hemispheric Views Discord.
- Notion: Where I store my “long term” notes, at least for now.
- Tusky: Mastodon client.
- Splitwise: Group expense management and splitting app. This was useful during our European trip last year, where each of us would take in turn to pay for the group.
- SunSmart: Used to track the current and forecasted UV index. Useful around this time of year if I’m planning to be outside for an extended period of time.
- Micro.blog: The Micro.blog app, although I occasionally use the web version too.
- 1Password: My password manager of choice.
- Realestate.com: Used to browse real-estate, out of curiosity more than anything else.
- Spotify: My “secondary” music app. I don’t use it for anything that I regularly listen to, but it’s occasionally useful for those once-off tracks.
- Google Authenticator: Where I keep my 2FA codes.
- Day One: Before I moved to a web-based journalling app, I used this Day One client for writing journal entries. It wasn’t perfect: there was always syncing delays to/from the Apple platform instances of Day One. But it was fine.
- Slack: Used mainly for work.
- Camera: I’m not sure why I have this here, since I almost always use the double power-button tap to bring up the camera. I guess I moved it here from screen one and never removed it.
- s3-browse: a TUI tool for browsing S3 buckets. This didn’t go beyond simply listing the files of a directory.
- scorepeer: An attempt to make a collection of online score-cards much like the Finska one I built.
- withenv: Preconfigure the environment for a command with the values of an
.env
file (there must be something out there that does this already). - About 3 aborted attempts to make a wiki-style site using Hugo (one called “Techknow Space” which I though was pretty cleaver).
-
Or possibly a Peertube client. ↩︎
Keyboard Maestro is coming into its own as a way for scheduling recurring tasks. I’ve just set one up for a daily report I need to run. It’s little more than a shell script so I probably could’ve used crontab to do it, but is so much easier configuring and testing it in Keyboard Maestro.
I recently got a new phone, a Pixel 9 Pro, which meant I needed to bring Alto Player up to date. I probably could’ve gotten away using the version I was using on my Pixel 6. But I didn’t have a binary build, and I needed to upgrade Gradle anyway, so I decided to spend a bit of time bringing it up to date to API version 35, the version used in Android 15.0. Fortunately it was only a few hours in total, and once I got it running in the simulator, I side-loaded it onto my phone and started using it.
It worked, but there were some significant UI issues. The title-bar bled into the status bar, the album image in the Now Playing widget was cropped by the curved corners of the phone, and the media notification didn’t display playback controls.
I set about fixing these issues today, starting with the title-bar and Now Playing widget. These was an issue with the views not respecting the window insets, and after a quick Google search, I found this article showing how one could resolve this by adding a ViewCompat.setOnApplyWindowInsetsListener and reacting to it by adjusting the margins of the view.
val topLevelLayout = findViewById(R.id.top_level_layout) as CoordinatorLayout
ViewCompat.setOnApplyWindowInsetsListener(topLevelLayout) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
leftMargin = insets.left
bottomMargin = insets.bottom
rightMargin = insets.right
// applying a top margin here would work, but will not have the toolbar
// background colour "bleed" into the status bar, which is what I want.
}
val t = v.findViewById<Toolbar>(R.id.toolbar)
t.updateLayoutParams<ViewGroup.MarginLayoutParams> {
// make the toolbar a little "narrower" than full height
topMargin = insets.top * 3 / 4
}
WindowInsetsCompat.CONSUMED
}
It took a few attempts, but I managed to get this working. Just using the top inset for the toolbar margin made it a little larger than I liked, so I adjusted the height to be 75% of the inset. This means the toolbar will actually encroach into the area reserved for cut-outs like the front-facing camera. This is arguably not something a “real” Android apps should do, but this is just for me and my phone so it’s fine.
I went through a few iterations of the album artwork cutoff on the bottom right corner trying to find something I liked. I tried bringing in the horizontal margins a little, but I didn’t like the alignment of the album art in the player, particularly compared to the covers that appear in the track list screen. One thing I didn’t try was raising the bottom margin so that it would fit “above” the curve. But those corners curve in quite a bit, and doing this would sacrifice a lot of vertical space. So I settled on hiding the album art altogether. It’s a bit of a shame to loose it, but at least it looks neater now.
The next thing I looked at was fixing the playback controls in the media notification. After some investigating, I found that this was because I was not setting the available actions in the PlaybackStateCompat builder. This, if I understand correctly, is used to communicate to various systems the current state of the playing media: what the track name is, whether it’s playing, whether one can skip forward or back. I have my own types for tracking this information — which is probably not correct but I wasn’t completely sure as to what I was doing at the time with Android’s media stack1 — and when I needed to convert this to a type understood by the framework, I made instances of this builder without setting the available actions. Earlier versions of Android seemed not to care, and the controls always appeared on the notification. But I guess they changed that.
One other thing I needed to do was to explicitly ask the user permission to show a notification before I could publish one. This is also relatively new: my experience with Android goes back to the early days where these permissions were disclosed up front when the app was installed. But I can completely understand why they changed it, as it was easy to simply tap through those screens with reading them. I am wondering whether media playback notifications are in some way exempt from these permission checks, as I was actually getting one to appear before I made this changes. But I figured it was probably worth doing anyway, so I added this permission request on first launch. Arguably I should be asking for this permission when playback starts, but again, this is just for me.
One final thing I needed to address were long album titles. The text view displaying the the album title had a width that autosized to the title itself, and the start and end constraints were set such that it appears centred in the view. This worked for “normal” length titles but when the length became excessive, the text view would fill the entire width of the screen and the title will appear left justified.
The fix for this was to set the text width to be calculated by the start and end constraints (setting layout_width
to 0dp
), bringing in the margins a little, and making the label text centre justified. I did this already for the track title, so it was easy to do this here too. Not sure why I didn’t do it earlier, or why I haven’t done it for the artist’s name yet.
This was all rushed, and I’ll admit I wasn’t 100% sure what I was doing. I was going down the route of trial-and-error to get this working, mixed in with web searches and a trip to ChatGPT. And yeah, the methods I used won’t make this a portable Android app that would work on every phone out there. But I’m reasonably happy with how it turned out.
Thanks for my new found fondness of buying mainstream music instead of streaming it, I needed a way to get these albums into Alto Catalogue. There exists a feature for fetching and importing tracks from a Zip referenced by a URL. This works great for albums bought in Bandcamp, but less so for any tracks I may have on my local machine.
I’ve managed to get Alto Catalogue building again after updating Webpack and a few NPM packages, so in theory, I could add an Upload Zip file action. But there’s more to this than simply accepting and unpacking a Zip file. I have to read the metadata, maybe even preview the tracks that will be imported, just in case I’m importing something I rather not (I did see this once, where zipping a bunch of tracks in the Finder introduced duplicates). This already exists for Zip files that are downloadable online.
I had a though about what my options are, until I remembered that I had a Gokapi instance running in Pikapods. So I tried using that to temporarily host the Zip file with a publicly available URL that could be read by Alto Catalouge.
The only problem is my internet upload speed is sooooo sloooooow. The Gokapi instance is hosted in Europe, and I suspect the instance itself is a little underpowered. So uploading 100 MB Zip files would take a fair bit of time: maybe 15-30 minutes. When I tried doing this via the web frontend, the connection timed out.
Fortunately, Gokapi has an API and one of the methods allows you to upload a file in “chunks,” which Gokapi will assemble back into the original file. Even better is that this chunking can be uploaded in parallel.
So I built a CLI tool which made of this chunking API to upload the Zip files. Once the upload is complete, the tool will display the hot-link URL, which I can copy-and-paste into Alto Catalogue.
The whole process isn’t fast (again, slow upload speeds). But it works, and I can use this tool to queue a bunch of uploads and let it do its thing while I’m doing something else. I really like tools that do this, where you’re not forced to babysitting them through the process.
There are a few limitations with it. It doesn’t allow for an awful lot of customisations on the lifecycle of the uploaded file. And the tool stalled out once when my computer went to sleep, and I had to start the upload from scratch. I could probably add something to track the chunks that were successful, allowing one to continue a stalled upload. If this happens frequently, I may look more into adding this.
But even so, this could be a useful addition to my use of Gokapi for transferring temporary files. If you think this might be useful to you, you can find the tool here.
Home Screen Of 2024
It’s just turned 3:00 in the afternoon, and I was alternating between the couch and the computer desk, racking my brain on what to do. With no ongoing projects — a few ideas have been bouncing around, yet none has grabbed me so far, and I had nothing else in a state where I could just slip on some music or a podcast and work on — and seeing a few others make similar posts on their blogs, I’d figured I talk about my home screens.
I realised that I haven’t actually done this before, mainly because my home screens change very slowly (the background hardly ever). Dramatic changes usually come about when I’m setting up a new phone.
And yet, I do want to talk a little about the apps I have at the moment, and I did want to make sure I had a record of how the home screens looked. And seeing that I needed to keep myself occupied doing something, now is as good a time as any.
Screen One
This screen contains two widgets — the date and weather widget at the top, and the calendar widget on the right — plus a small collection of apps placed deliberately where they are. The apps I have here are not necessarily the most used (although two of them are) but I like having easy access to them for various reasons.
Aside from the widgets, the apps I have on this screen — from left to right, top to bottom — are as follows:
The items in the dock are as follows:
Screen Two
A grab-bag of apps I frequently use. Some of them probably should be on the first screen, but since real-estate is at a bit of a premium I just keep them here, and swipe over when I need them.
From left to right, top to bottom, the apps on this screen is as follows:
Screen Three
This is a screen I hardly ever used, as it’s mainly reserved for apps that are useful while travelling. The Booking.com app and Emirates apps I can probably remove: I was using them mainly to track flights and accomodation during my European trip last year.
The only one worth keeping is Airalo, which allows you to buy and setup data SIMs that work overseas. This has been really useful to me during my last couple of trips, and I hope to keep using it for trips in the future. It doesn’t offer a lot of data, but any data is better than zero data, as my friends — who continued asking to use my data when we’re out of WiFi range — can attest.
Released version 1.2.0 of Sidebar for Tiny Theme. In this version, the sidebar can now be configured to appear on pages other than just the home page. Options include showing it on the pages of posts, or pages other than posts. With both on, the sidebar will now appear on all pages of the site.
Thought I’d have another go at looking at BoxedWine for making an online archive of my old Delphi projects. They’ve been some significant improvements since the last time I looked at it. They don’t run fast, but that’s fine. As long as they run.
That Which Didn't Make The Cut
I did a bit of a clean-up of my projects folder yesterday, clearing out all the ideas that never made it off the ground. I’d figured it’d be good to write a few words about each one before erasing them from my hard drive for good.
I suppose the healthiest thing to do would be to just let them go. But what can I say? Should a time come in the future where I wish to revisit them, it’d be better to have something written down than not. It wouldn’t be the first time I wished this was so.
Anyway, here are the ones that were removed today. I don’t have dates of when these were made or abandoned, but it’s likely somewhere between 2022 and 2024.
Interlaced
This was an idea for a YouTube client1 that would’ve used YouTube’s RSS feeds to track subscriptions. The idea came about during a time when I got frustrated with YouTube’s ads. I think it was an election year and I was seeing some distasteful political ads that really turned me off. This would’ve been a mobile app, most likely built using Flutter, and possibly with a server component to get this working with Chromecast, although I had no idea how that would work.
This never got beyond the UI mock-up stage, mainly because the prospect of working on something this large seemed daunting. Probably just as well, as YouTube solved the ads problem for me, with the release of YouTube Premium.
Red Crest
I thought I could build my own blogging engine and this is probably the closest I got (well, in recent years). This project began as an alternative frontend for Dave Winer’s Drummer, rendering posts that would be saved in OPML. But it eventually grew into something of it’s own with the introduction of authoring features.
I got pretty far on that front, allowing draft posts and possibly even scheduled posts (or at least the mechanics for scheduled posts). One feature I did like was the ability to make private posts. These would be interleaved with the public ones once I logged in, giving me something of a hybrid between a blogging CMS and a private journal. It was also possible to get these posts via a private RSS feed. I haven’t really seen a CMS do something quite like this. I know of some that allow posts to be visible to certain cohorts of readers, but nothing for just the blog author.
In the end, it all got a bit much. I started preparing the screen for uploading and managing media, I decided it wasn’t worth the effort. After all, there were so many other blogging CMS’s already out there that did 90% of what I wanted.
Reno
As in “Renovation”. Not much to say about this one, other than it being an attempt to make a Pipe Dreams clone. I think I was exploring a Go-based game library and I wanted to build something relatively simple. This didn’t really go any further that what you see here.
SLog
Short for “Structured Log”. This was a tool for reading JSON log messages, like the ones produce by zerolog. It’s always difficult to read these in a regular text editor, and to be able to list them in a table made sense to me. This one was built for the terminal but I did make a few other attempts building something for this; one using a web-based GUI tool, and another as a native MacOS app. None of these went very far — turns out there’s a lot of tedious code involved — but this version was probably the furthest along before I stopped work.
Despite appearing on this list, I think I’ll keep this one around. The coding might be tedious, but I still have need something like this, and spending the time to build this properly might be worth it one day.
Miscellany
Here are all the others that didn’t even get to the point that warranted a screenshot or a paragraph of text:
I’m sure there’ll be more projects down the line that would receive the same treatment as these, so expect similar posts in the future.
I’m not a fan of the changes Google made to their Weather app. It assumes you’re interested in saving every location you search for as a favourite, which is not how I use search. And horizontal scrolling for the 10 day forecast? With no date?
No, sorry. This is a step backwards in design.
Exploring Godot to see if I could use it to make a card game. I got this far:
Yep, I’m on a roll. 😄
Might need to work through a couple Godot tutorials first, just so that I understand the basics.
I plan to integrate UCL into another tool at work, so I spent last night improving it’s use as a REPL. Added support for onboard help and setting up custom type printing, which is useful for displaying tables of data. I started working on the tool today and it’s already feeling great.
If there’s one thing I’d like to see added to Go for 2025, it’s type parameter support on methods. It’s still not possible to do something like this:
Which is a real shame, as I’ve got some ideas on how I could use these. Building something like Java streams, for example.
Some more work on that feed reader app. You know how I said that I wanted to hold off looking at appearances? Well, I abandoned that approach when I installed the app on my phone and tried viewing a few articles. And oof! There’s work to be done there.
First, it’s slow. Very slow. It’s taking a good second or two to pull feeds and entries from Feedbin. I was expecting this, and I’ve got a few plans on how to speed this up. But the biggest concern is the janky list scrolling. I mean, I wasn’t expecting the buttery smoothness of iPhone list scrolling, but I expected Flutter to be better than what I was experiencing. I’m hoping that it’s just because I was running a debug build, but part of me fears that Flutter is just not optimised for smooth list scrolling, favouring ease of development and a common runtime. I rather not change frameworks now, especially after spending an evening dealing with all the build issues, but I don’t want to live with this for ever.
But speed is not the biggest issue. The biggest offender was the feed reader view. The embedded web-view was only lightly styled, and it felt like it. The margins were all off, and I didn’t like the default font or colours. It made reading the article a bad experience to a surprising degree. I’ve dealt with rushed or poorly designed UIs in the past, but I didn’t have much tolerance for this. Not sure why this is, but I suspect it’s because I’ve been using feed readers that put some effort into the design of their reader screen.
In any case, a couple of evenings ago, I decided to put some effort into the styling. I replace the body text font with Noto Sans and the fixed-font with Ubuntu Mono. I dropped the font-size a little to 1.05 em (it was previously 1.1 em, with felt a little big, and 1.0 em felt a little small). I bought the margins in a little. And I styled the block-quote, figure, and pre elements to an appearance that, despite being a little overused, felt quite modern.
The results look much better, at least to my eye (and my emulator). Here are some side-to-side comparison shots of the changes (left side is the unstyled version, while the right side has the new styling changes):
I still need to actually install this on my phone and try it out. I’m wondering whether I should do so after a bit more work syncing the read status with Feedbin. That’s a feature that’s keeping me on Feedbin’s PWA for now.
Spent the last few evenings continuing work on a Flutter-based RSS feed reader. This project is now further along then my previous attempts at doing this. I’m at the point where feeds and feeds items are being fetch from Feedbin and displayed in a list view:
The aesthetics are taking a bit of a back seat in favour of functionality for now; I haven’t even changed the default accent colour. But the infrastructure is there: tapping a feed will bring up the entries for that feed. This is using named routes for navigation, and cubits for state management. It’s a bit more work upfront, but it does make for a neater codebase.
The biggest challenge so far was getting the actual reader view working. I hoping to use the webview plugin, but when I tried adding it, I ran into a bunch of Gradle errors. These were either class version errors or dependency errors, depending on what I tried to fix it (I didn’t get screenshots, sorry). I eventually stumbled upon this Flutter Gradle plugin migration guide, and following this, along with upgrading Java to OpenJDK 25, got Gradle working again.
But I was still getting build errors. The first couple were Gradle plugins com.android.application
and org.jetbrains.kotlin.android
that needed to be updated. Easy stuff. And then I got this error message:
Execution failed for task ':webview_flutter_android:compileDebugJavaWithJavac'.
> Could not resolve all files for configuration ':webview_flutter_android:androidJdkImage'.
> Failed to transform core-for-system-modules.jar to match attributes {artifactType=_internal_android_jdk_image, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
> Execution failed for JdkImageTransform: /Users/leonmika/Library/Android/sdk/platforms/android-34/core-for-system-modules.jar.
> Error while executing process /Users/leonmika/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/jlink with arguments {--module-path /Users/leonmika/.gradle/caches/8.10.2/transforms/575ccd1a7426c0be21d9fe3a81898be3-05a021da-a1a7-409f-a30a-bba769b57371/transformed/output/temp/jmod --add-modules java.base --output /Users/leonmika/.gradle/caches/8.10.2/transforms/575ccd1a7426c0be21d9fe3a81898be3-05a021da-a1a7-409f-a30a-bba769b57371/transformed/output/jdkImage --disable-plugin system-modules}
Running a web search on the error revealed this Stack Overflow answer, which resolve it. There were still a few complaints about the the NDK version but after all that, the app finally launched with the web-viewer.
I still need to actually render the entry, plus style the HTML a bit. The immediate goal after this, once the reader view, is getting this on my phone to start playing with it. It’s just barebones for now, but I find that the sooner I can start using a project myself, the more likely I am to keep at it.
Oh, it turns out it’s an older style of referencing targets and is no longer supposed to be used. That’s a shame.
Upgraded my work laptop to Sequoia. “Love” the experience that this new version provides, especially the mouse-and-patience exercise I get in the morning. 👎
<img src=“https://cdn.uploads.micro.blog/25293/2024/cleanshot-2024-11-26-at-07.30.252x.png" width=“600” height=“541” alt=“Three permission requests stacked up, with the top one displayed asking if an app called “Obsidian” can find devices on local networks, with options to “Don’t Allow” or “Allow”.">
Now this is cool: Hetzner has opened up a region in Singapore. The tyranny of distance is starting to abate.
Now that my 1Password subdomain woes with Android Vivaldi has been tamed, it’s time to turn my attention to Safari:
Building out the meta elements of Cyber Burger, including the “menu du jour” a.k.a. the main menu. I’ve used food-service terms for the menu items to maintain the theme, but there is a button to switch them over to more conventional names should it be too unclear.
Title design this morning. Trying to get as close as I can to the Cyberspace Raceway font as my pixel art skills will allow for.
I finished my experiment with htmgo, building the worlds most inefficient world clock. It uses HTMX swapping to get the time from the server every second.
It’s an interesting framework. Not sure it’s fully ready yet (you can’t change the bind port, for example) but might be useful in the future.