Categories
Technology

Serving ‘files’ in Vapor

In my experience, dynamically generating a file, serving it immediately, and not persisting it on the server is a pretty common use case. In general, this is one of two things – either a PDF download, or a CSV. While my Vapor tinkering hasn’t yet given me an opportunity to generate PDFs on the server, I have had an occasion to create a CSV, and wrote up a little helper for doing so.

import Vapor

struct TextFileResponse {
    enum ResponseType {
        case inline, attachment(filename: String)
    }
    
    var body: String
    var type: ResponseType
    var contentType: String
}

extension TextFileResponse: ResponseEncodable {
    public func encodeResponse(for request: Request) -> EventLoopFuture<Response> {
        var headers = HTTPHeaders()
        headers.add(name: .contentType, value: contentType)
        switch type {
        case .inline:
            headers.add(name: .contentDisposition, value: "inline")
        case .attachment(let filename):
            headers.add(name: .contentDisposition, value: "attachment; filename=\"\(filename)\"")
        }
        return request.eventLoop.makeSucceededFuture(.init(status: .ok, headers: headers, body: .init(string: body)))
    }
}

That’ll work for any file you can assemble as text; CSV just struck me as being the most useful example. Use ResponseType.inline for a file you want displayed in a browser tab, and .attachment if it’s for downloading.

And if you’re doing a lot of CSVs, give yourself a nice little helper:

extension TextFileResponse {
    static func csv(body: String, name: String) -> TextFileResponse {
        .init(body: body, type: .attachment(filename: name), contentType: "text/csv")
    }
}
Categories
Technology

“All organizational systems fall on a spectrum from Calendar to To-Do List”

Something I said to a coworker recently. Largely inspired by listening to Cortex, and I felt like giving it a slightly more visual treatment.

Categories
Technology

Default Values in Vapor Fluent

My recent tinkering has been with Vapor, and while I mostly like their Fluent ORM, it has some rough edges and semi-undocumented behavior. At some point, I’ll feel confident enough in what I’ve learned through trial and error (combined with reading the source code – open source!) to actually make some contributions to the documentation, but for now, I’m going to throw some of the things I struggled with up here.

If you’re using a migration to add a column, and specifically want it to be non-null, you’ll need a default value. My first approach was to do a three-step migration, adding the column as nullable, then filling the default value on all rows, and then setting the column to be non-null, but that didn’t feel right. Eventually, though, I figured out how to express a DEFAULT constraint in Fluent:

let defaultValueConstraint = SQLColumnConstraintAlgorithm.default(/* your default value here */)

Then, in your actual schema builder call:

.field("column_name", /* your type */, .sql(defaultValueConstraint), .required)

Note that SQLColumnConstraintAlgorithm isn’t available from the Fluent module, you’ll need to import SQLKit first.

And here, a full worked example:

import Vapor
import Fluent
import SQLKit

struct DemoMigration: Migration {
    func prepare(on database: Database) -> EventLoopFuture<Void> {
        let defaultValueConstraint = SQLColumnConstraintAlgorithm.default(false)
        return database.schema(DemoModel.schema)
            .field(DemoModel.FieldKeys.hasBeenTouched, .bool, .sql(defaultValueConstraint), .required)
            .update()
    }
    
    func revert(on database: Database) -> EventLoopFuture<Void> {
        database.schema(DemoModel.schema)
            .deleteField(DemoModel.FieldKeys.hasBeenTouched)
            .update()
    }
}

(For context, I’m in the habit of having a static var schema: String { "demo_model" } and a struct FieldKeys { static var hasBeenTouched: FieldKey { "has_been_touched" } } within each of my Fluent models – it keeps everything nice and organized, and avoids having stringly-typed issues all over the place.)

Categories
Review

“The Last Thing He Wanted”

Joan Didion

This book took a while to really capture my attention, in terms of time. In terms of how far into the book it took, I suspect it was about the usual amount of time it takes a book to grab me. The distinction being, usually I read books like I’ve got a grudge, like I’m trying to see how fast I can cram all these words into my brain. Not so, with this one — I’d read a chapter or two, and put it down. Sometimes for a couple minutes, so I could sit and process a bit, and then pick it up and continue; other times, it’d be a day or two before I tried again.

All in all, this isn’t the kind of book I tend to go for. It feels much more Literary than my default — which is largely the writing style, but something about the paper and the typesetting makes it feel like the kind of book I’d read for English class in high school, filling it with notes and highlights and a ridiculous amount of sticky notes.

By the end, it feels… semi-coherent. Which, by then, you’ve grown used to, because at the beginning it’s entirely incoherent. The writing style is “first draft of a book by somebody who got a doctorate on a specific week of history and has no grasp of the concept of expert blind spot.”

At the end, though, I liked the book. Apparently it’s been developed into a Netflix film, the cover tells me; I may watch it, because I can’t imagine the film adaptation at all feeling like the book.

In writing this, I can also tell just how much Didion’s writing style has influenced mine, at least at the moment. Consider this a cheap knock-off of a demo. And then go read the real thing, instead.

Categories
Review

“The Counterfeit Viscount”

Ginn Hale

I don’t think I read the word ‘viscount’ a single time in this book without thinking of Enola Holmes, but that was a fun movie, and this was a fun book, so it all worked out okay.

Like the last book of Hale’s that I read, there’s a great deal of fun worldbuilding going on in a short read. Another alternate history thing, in an entirely different direction, and once again it provides a fun backdrop for a simple enough story.

Admittedly, the mystery itself is a bit convoluted, but it feels like a backdrop for the romance angle, so it can get away with it.

It’s a short read, so I think this short review will suffice. It’s a fun little story, with a silly little romantic plot, and sometimes that’s what you need. If that’s what you’re in the mood for, give it a read.

Categories
Review

“Floodtide”

Heather Rose Jones

The introduction to this book was familiar enough that I did a quick search and found out I’ve read another book in this universe.1 I may go back and reread that one now, in fact, because I think that “Floodtide” did a better job of introducing the system of magic in a way that makes sense to my brain.

It’s also, largely, a much more human-scale story. The protagonist isn’t changing the world, she’s just trying to get through life, finding a little bit of happiness along the way. Sure, she has friends changing the world, living a grand, romantic life, and she’s determined to help them do that as best she can, but she’s still… a regular person. Sometimes, it’s nice to read things like that — it’s what got me watching Agents of SHIELD back when it first aired, after all.2

It reminds me, a little, of the idea of a space opera. There’s all sorts of large-scale things happening in the backdrop, but the actual core of the story is about the characters and how they’re doing, why they make the choices they do, that sort of thing.

I’m not certain how well I’m selling this book, but I did quite like it. Give it a go.

  1. That was more than three years ago, now? Somehow, in my head, none of my ongoing projects have actually been ongoing that long, and yet, here I am, several years into writing little book reviews.
  2. And, y’know, once Agents started being about saving the whole world instead of just, y’know, regular people trying to exist in a world with superheroes, I gave up on it.
Categories
Review

“The Strange Case of the Alchemist’s Daughter”

Theodora Goss

This book reminded me of the 2017 remake of The Mummy. Which, I must admit, sounds like an insult, but hear me out: this book is what that movie wanted to be.

The premise is fairly simple: what happened to Dr. Jekyll’s family? (And, further, what happened to any of the background characters in any of the popular novels of the time?)

And from that question, Goss made a marvelously interesting story. She’s establishing a shared universe for a lot of these stories, pulling together the literary zeitgeist of the whole period into a single interlinked whole, in a delightful way.

Beyond that, the actual writing style is very well done. There’s a main protagonist, and the story is mostly told from her viewpoint, but there are interjections from the other characters, and you learn fairly quickly on that, though she’s the protagonist, she’s not actually the one wring — just giving the occasional editorial comment. It reads like the, oh, third draft of a book, where you can still see all the margin notes thrown in by the various people reading through and remarking on their own perspective of the events in the book.

Very early on, this disorganized style is used for what I think is the most interesting piece of foreshadowing I’ve read in quite a while — one of the more impatient characters leads in with “no, no, you should start in medias res, like this” and suddenly we’ve skipped forward several chapters, to a very exciting scene, for something like half a paragraph, before we’re pulled back to where we were with “now hold on, they won’t know what’s going on if we jump right to there!” It is, frankly, delightful.

I very much enjoyed this book — as evidenced by my reading it in a single sitting — and highly recommend it. Give it a go, and, if you need me, I’ll be adding the sequels to my wish list.

Categories
Review

“The Voyages of Cinrak the Dapper”

AJ Fitzwater

I very nearly gave up on this book halfway through, the point of putting it down and not picking it back up again until a couple months had passed. I’m glad I gave it that second chance, though, because once I was over that hump, I quite enjoyed it.

That midpoint was where the amount of ‘fantasy’ in this fantasy novel jumped up by a lot. Because, yes, it’s a book about a capybara pirate, so of course the whole thing is a fantasy novel.1 But where it nearly lost me was in changing from “here’s a bunch of tropes that I’m using to make some characters I like” to setting up a whole new mythology unlike any I’ve seen before. And if I’d given up, that would’ve been a shame, because this new mythos is downright beautiful. I can’t honestly say that I follow every part of what’s going on, but I also can’t really say that I mind, because, again: beautiful.

I’m trying very hard not to spoil anything, because it all ties together so well. Suffice it to say that if you aren’t invested by the end of the story where Agnes makes her first appearance, you have my permission to give up on the remainder of the book.

Hopefully that won’t happen, though. Give it a try.

  1. You could also make it science fiction, assuming that there’s been an uplift and possibly some sort of apocalypse in the interim, but that’s pushing so close to the “sufficiently advanced technology” line that it may as well be a fantasy novel at that point.
Categories
Review

“What If?”

Randall Munroe

A magnitude 15 earthquake would involve the release of almost 1032 joules of energy, which is roughly the gravitational binding energy of the Earth. To put it another way, the Death Star caused a magnitude 15 earthquake on Alderaan.

This is a fun book to recommend, because unlike most books, there’s a demo available online. Go read that, and if you like it, the book contains more. It also has a very literal subtitle: “serious scientific answers to absurd hypothetical questions.”

Munroe has had a fascinating career to date, and I remain an avid fan of his webcomic. It was definitely a formative influence on the nerdier side of my sense of humor,1 and continues to make me laugh an average of slightly more than three times a week.2

This is a fairly good book for reading in small chunks – each ‘chapter’ is only a few pages long, and there’s no need to read them in any specific order.

All in all, it’s a fun read, and I definitely recommend it.

  1. And, in writing that, I’m having fun imagining his reaction to reading that.
  2. Three new comics a week, and the average is above that because sometimes I wind up hitting the ‘random’ button a few times and laughing again.
Categories
Review

“You Suck at Cooking”

(Unknown Author)1

Seafood is a marketing term that was invented to convince people that ocean creatures are edible, rather than the stuff nightmares are made of.

This is, I think, the best cookbook I’ve ever read. Which, admittedly, doesn’t sound like a ringing endorsement, but I’ve read a frankly alarming number of cookbooks.2 So trust me when I say that this one is well worth the read. And, indeed, is worth actually reading straight through — though, aside from the introductory chapter, you can use it in the more conventional cookbook manner, and flip through the section you’re interested in at any moment.

Because, here’s the thing: not only is it funny — and of course it was going to be funny, it’s by You Suck at Cooking — it’s also smart. Smart, and clever, and… honest. It’s a masterwork of Being A Millennial, is what it is.

It is also, genuinely, an excellent introduction to cooking. I grew up cooking, so the kitchen holds no fear for me.3 In that regard, I’m not the target demographic of this book. The core audience here are the people who didn’t grow up being taught to cook, the people who might want to figure it out but are facing down a pile of unknown unknowns.4

So, if you’re looking for something lighthearted and fun, or if you don’t know anything about cooking and want a good starting point that’ll remind you you can do this, or you’re looking for some interesting new recipes to try — because there are some of those in there, too! — then I highly recommend this book. Check it out.

  1. I mean, there’s probably enough information about the guy online now that you could figure out who he is, but hey. Don’t be creepy.
  2. Listen, my family has a cookbook-buying problem, and at a certain point we needed to downsize the collection. But we couldn’t just give them away, we had to read them first, and maybe copy down our favorite recipes…
  3. Well, unless you own a mandolin, in which case, I fear the mandolin, as should you.
  4. To take a bit of a tangent, it reminds me of the general reaction to Antoni on the first season of Netflix’s Queer Eye. “Some professional chef, all he taught them was to make guacamole? He’s just there to be eye candy.”
    Well, no, Internet Strawman. What, is he gonna take somebody from “only thing in their fridge is a bottle of ketchup” to making a five-course meal in a week? No. He’s going to start with something basic to take away the “oh god I don’t know what I’m doing,” and (I assume) give them some tips on how to continue learning.
Categories
Review

“What Einstein Told His Cook”

Robert L Wolke

In my mind, the term for this genre is “popular science.” Or, possibly, “pop science.” (In this case, that’s also a pun on the subject.) Either way, it feels like a fun piece of beach reading – worth the time to read, which differentiates it from an airplane read,1 but not so heavy that you feel like you should be taking notes or pausing to take time to process.

For the most part, this book stands up pretty well, and the cover is minimal enough that the whole thing feels quite modern. Admittedly, it loses some of this with the occasional dated pop culture reference, and the final chapter, discussing the latest technologies, noticeably lags as a result of being, dear lord, almost two decades out of date.2

Still, though, it’s not like chemistry changes all that rapidly, and a lot of the explanations of how things work were quite neat. Give it a read.

  1. For my own ‘pop science’ injection: despite their pressurized interiors, the amount of oxygen in the cabin of a plane is lower than what your brain is used to, so as the flight goes on, you get a little oxygen-deprived, leaving your thoughts nice and fuzzy. There’s a reason Clive Cussler books are the ideal airplane books – they’re incredibly formulaic, so there’s less cognitive load.
  2. There’s a very serious discussion of the differences between mechanical and digital cooking thermometers, which is downright comical in the age of RFID-tagged disposable cups.
Categories
Review

“Becoming Steve Jobs”

Brent Schlender, Rick Tetzeli

Moving backwards, there were three things about this book that really captured my attention.

Lastly, the discussion of what Steve Jobs was like when he wasn’t being… what everyone thinks of when they think of Steve Jobs. The authors reiterate, many times, that the image of Jobs as alternating between ‘a genius’ and ‘an asshole’ was formed when he was very young, skyrocketing to fame at the helm of Apple. Later in life, he’d softened, become better able to have constructive discussions with people instead of just tearing into them – but, to the detriment of his public image, he’d also gotten very good at keeping out of the public eye when he wasn’t being Steve Jobs On Stage. Nobody was really afforded the chance to publicize that newer version of Steve Jobs.

Secondly, I’d never realized how integral to Pixar he was. At most, I knew he’d been involved in the company, led it for a while at some point; I hadn’t realized that he was the owner, one of the original people who built the company out of an immense talent pool bought wholesale from LucasArts. My mental timeline of Steve Jobs, betraying my tech industry bias, went Apple-NeXT-Apple. Pixar was an immense thing to miss out on, and realizing how much he’d shaped both Pixar and, eventually, Disney has me even more respecting the impact Jobs has had on our society.

And firstly, I found myself, over and over, contemplating the scale of technological change that happened within the lifetime of the company he and Wozniak founded. I think about these comparisons a lot, so here’s some of my favorites:

  • A single AirPod has more onboard processing power than any given Apollo launch.
  • Every Apple Watch, even the glacially slow Series 0, has had more processing power than a Cray-2.1
  • You can fit the entirety of the original version of MS-DOS in the L1 cache of a single core of a modern i9.2
  • I’d have to do a lot more math than I feel like doing to confirm this, but it’s not unreasonable to say that the iPad Pro I’m writing this on probably packs more computing power than every Apple II ever sold, combined.

And, even more than all those “ooh, it can do lots of math even faster” comparisons, the thing that kept striking me – reading this, as I was, on an iPad Pro – was just the staggering technological capacity of everything I do with this device. It’s a multitouch touch screen, with a battery of onboard radios, enough storage space for every book ever written; it’s got a lovely keyboard and stylus, both of which attach using only magnets. This device is a miracle of modern technology, and I’ve gotten very used to it. Reading about the Altair 8800, with its toggle switches and LEDs, gave me just enough decontextualization to look at this magical slab of glass and think, wow. Wow.

After reading this book, I think that sort of moment is something Steve Jobs would’ve loved to see.

All in all, I really enjoyed the book, and I highly recommend it. It was nice to see a more balanced look into Jobs’ life, a more human side of the man who so indelibly shaped the modern world. Give it a read.

  1. Surprisingly difficult to validate this comparison to my own satisfaction – the Cray-2 was in the era of “here’s how many FLOPS this baby can do,” but these days it’s just “what’s the GeekBench score?” and there’s no direct comparison between the two.
  2. I couldn’t find the actual size-on-disk of the original MS-DOS release, but based on the limitations of the file system, I can reasonably assume it’d fit.
Categories
Technology

State of the Apps 2020

I suppose I’m making this a tradition, now, writing up what I have on my phone and what’s changed since last year. And why not? It’s fun, and it helps me a bit with the fact that I’ve let my blog post queue get very near empty.

Screenshot of the iOS 14 'today' view, showing several widgets.
Screenshot of an iPhone home screen, with a mix of widgets and applications.

This year saw the release of iOS 14, and with it, the ability to put widgets directly on your home screen, and to banish apps from your home screen to the App Library. Both of which I have pretty thoroughly taken advantage of – though I’ve only got the one page of apps, I almost certainly have more apps installed this year than I did last year.

Widgets

Let’s do a quick look at my ‘widgets’ screen. I believe the official name is ‘Today View,’ but that’s a piece of information that I’m going to estimate seven people outside of Apple know off the top of their head, so we’ll move right along.

The upper half is a dashboard; at top left, we have a Smart Stack, showing Calendar above, and beneath it are a pair of Timery widgets that show me totals I want to keep an eye on throughout the day.

Top right, batteries; I used to think the idea of the bigger battery widget was ridiculous, but if I do everything precisely wrong, I can overwhelm it – think, phone, watch, AirPods with distinct battery levels, and the AirPods case, to boot. Still, I like that at-a-glance view, and I actually like that it doesn’t show percentages, it feels a lot lighter as a result.

Below that, I’ve got another Stack with a pair of Things widgets, showing my Today and Upcoming lists. I originally had a couple of my Areas displaying, as well, but found I wasn’t really using them.

Finally, I’ve got another Stack, this time a pair of the larger-form Timery widgets. The one you’re seeing is my “my projects” collection – including a deliberately-blank bottom-right, so that with a timer running I’ve still got a way to tap into the app without starting or stopping a timer. 1 The other one, which I won’t be showing for “NDA” reasons, is stuff for work.

Home

Now the home screen, which my mental model has in five segments.

The four apps at top left are the “aspirational” section – Books, as I’m trying to train myself to reach for a book rather than searching the web for Content to keep myself entertained; fitbod, as part of my ongoing fitness routine/goals; Shortcuts, because I want to be free to automate tasks with ease; and Files… doesn’t particularly fit the theme, but I use it often enough for it to have earned that spot.2

Top right is the ‘health’ pile. It is, you guessed it, yet another Smart Stack.3 Topmost is FoodNoms, which I still heartily recommend to anyone who wants to start calorie counting.4 Below FoodNoms we have Streaks, which I’m using less than I did last year, but I still find it helpful. Despite the fact that I’ve been taking the same meds every morning for several years now, I still forget at least once a week, and Streaks is what reminds me. Finally, at the bottom, is Activity, which I think you could call one of the canonical widgets of the new style – a glanceable bit of information, always there.

Below these two we have… an unnamed section.5 It is, once again, a Smart Stack. On top we’ve got my main-use Shortcuts – the bottom two for playing music, ‘Things’ gives me a menu of various Things items/projects that I use semi-often, and ‘Auto’ is a lovely piece of work that does what Siri Suggestions was advertised as doing.6

Below Shortcuts is Weather. Apple’s Weather app still feels a little lacking in accuracy compared to Dark Sky, but I’m hoping they’ll rectify that (and get their display of “amount of rain” lining up with my actual expectations for what it means, a la Dark Sky) before they disappear Dark Sky entirely. The widget, though, makes me want to write a chapter for a UI textbook about how well it contextually displays information.

The final item in this stack is Fluidics. It’s not just shameless self-promotion, it’s also dogfooding! (And I really do think the widget is a beautiful piece of design, if I do say so myself.)

The bottom section is Regular Ol’ Apps.

  • Overcast is holding steady as my podcast app. I’ve finally gotten below 5 gigs of podcasts downloaded to listen to, so in the next month or so I expect Chase to finish convincing me I need to download the entire back archive of Roderick On The Line.
  • Photos has actually grown in how much I’m using it – I decided to go all-in on it this year, and spent some time loading a bunch of the photos from my DSLR archives in, and some more time labeling faces so the ‘people’ album would work. I’ve had mixed results.7
  • Mail. What do you want me to say? It’s Mail, and I wanted the most boring of email apps.
  • Reeder I’ve updated to version 4, and am continuing to drive the actual RSS sync off of TT-RSS/Fever on my Synology. The one addition is RSS-Bridge, which I’m using to scrape a few Twitter feeds into RSS as well. I’ve also finally moved wholesale into Reeder’s Read Later service, leaving Instapaper behind.8
  • Ulysses still fulfills the same use case for me. I’ve found it to be a… reasonable editor for GitLab Wiki articles, and a much better viewer for them than GitLab itself.9
  • Day One has continued to expand the list of things I use it for. I think the most interesting is a pair of journals I’ve got – “Inbox” and “Archive.” “Inbox” is in as dark a theme as I can make it, and is the default journal on my phone; any time I’ve got a midnight idea, I jot it down in there, and once a week or so I’ll go through, processing things from “Inbox” into “Archive.” It’s a nice little workflow.
  • Slack made its way onto my home screen courtesy of MHCID, and remains there because it’s the main way I communicate with some of the friends I made through the program. It’s a much better UI than Teams.10
  • Paprika might belong in the ‘aspirational’ category in place of Files. I’ve got more than a thousand recipes in here, and I’ve made, like, twenty of them. One day…

Finally, we have the dock, which is only a visual distinction given that I’ve only got the one page.

  • Music remains a very important thing to me, and I’m in and out of it all day. Every time I use it, I miss when Apple allowed you to customize the tabs – they have five tabs in there, and I literally never use three of them. Let me have playlists as a top-level tab, Apple, please. Stop trying to make Radio happen.
  • Messages is the only social network I’ve got, these days. It’s nice to see Apple putting effort into it – I am a heavy user of threads and tapbacks.
  • Things is a stalwart as my task management app. Outside of drawing apps, it’s the only iPadOS app that does handwriting recognition correctly – you just start writing, anywhere on screen, and it reads it in.11
  • Safari, because what would an iPhone be without the internet communicator? Admittedly, my Safari is a very different Safari than most peoples’, because I’ve got a mountain of content blocker rules via 1Blocker, and on top of that I have JavaScript disabled.12
  1. You may have noticed that the Timery app icon isn’t present on my home screen – I like this way of getting to it.
  2. I suppose you could call it part of the Automation subcategory, considering that I’ve got a lot of iCloud Drive -> Hazel stuff going on…
  3. I absolutely love the stack mechanic; my only complaint is the little bit of animation-delay between when I finish swiping and when I can tap to interact. Yes, Apple, the little ‘settling into place’ animation is lovely… but I’m trying to do things, so get it out of my way and let me do them.
  4. It’s a beautiful, and very iOS-y piece of work. The food database isn’t as full as MyFitnessPal’s, but that’s honestly a good thing – MFP’s database is full of trash data. FoodNoms starts with the FDA’s database, and has a ‘community-sourced’ database on top of that, where every entry has been manually validated, so it’s solid. If something isn’t in there, tap a button and scan the nutrition label, and the app reads the whole thing in – and then, once you’re done, asks you if you want to submit the resulting data to the community database. It’s an incredibly slick interaction, and I adore it.
  5. I wasn’t really planning on the naming at all when I started writing this, so it makes sense that I’d run out eventually.
  6. The tl;dr version is “it checks the time and some other contextual information and automatically picks from a list of other shortcuts to run based on that.” My morning routine is a series of single taps on that button, and it feels downright magical.
  7. It can identify my grandmother with ease, regardless of if the photo is from this year or a scan of one of her wedding photos; my grandpa, on the other hand, it can’t spot if I give it two of the same photo and manually tag him in one.
  8. I’ve still got Instapaper connected to Reeder, on the off chance that I have to use the Windows machine my work provided, but I’m something like 99.5% on macOS these days, so that’s exceedingly rare.
  9. We’ve got a wiki monorepo kind of thing at work, where we’ve got articles on anything that may be useful. GitLab’s wiki can show something like 15 pages at a time in the list, and makes it rather difficult to find that list at all; they really didn’t expect anyone to use it like this. However, you can sync the whole thing, like any other repo, at which point you’ve got a regular ol’ folder full of Markdown files, and Ulysses handles that pretty well. It does have a bad habit of escaping escape characters, and I know I’ve got at least one file somewhere that opens with something like 30 backslashes before a single tilde. Whoops.
  10. Teams, which we use at work, isn’t on my phone at all. Maintain that work-life balance, folks.
    While I’m talking about Teams: the UI, across the board, feels like exactly as many little “oh, nobody thought about how this interaction would go” and “oh, nobody tested this” moments as I expect from any Microsoft product. Unfortunately for my distaste for Microsoft products, it has one notable advantage over Slack – calling support. Slack’s iOS app still doesn’t support video calls, so for actual workplace purposes it’s effectively useless. (And yes, I am hoping someone at Slack will cite this as evidence to give the iOS app the resources it needs to get that feature.)
  11. This has been a subtweet at Messages, whose support for handwriting recognition consists of “you may write up to two words, and you’ll probably drop the iPad trying to do it.” If iPadOS 15 doesn’t make the entire thread pane a valid handwriting recognition target, I’m going to have to write Tim Cook some very unhappy emails.
  12. And this is a subtweet at every news site that either entirely fails to render without JavaScript, or doesn’t load images without JavaScript. You are weak, and I scoff at you.
Categories
Review

“Catfish Lullaby”

A.C. Wise

About 2/3 of the way through this book, I wound up texting a friend, “I didn’t want t get invested in this book, because it’s creepy, but here I am, queueing up the nightmares.”

And, really, that’s a great summary of the book. It’s definitely creepy, but it’s also enrapturing. Think of… a swamp. It’s a place of decay, and death – but also, full of so much life. Beautiful, and terrible; ancient, but always changing. That’s how the story feels, all the way through.

In short, it’s excellent. Not too long a read, so not too long a review, but I quite liked it. Check it out.

Categories
Review

“Wayward Son”

Rainbow Rowell

I enjoyed “Carry On” so much that I immediately picked up the sequel and read through it. “Wayward Son” is also a fun read, but not nearly as strong as “Carry On” was; “Carry On” is a conclusion and a beginning, while “Wayward Son” is… the middle book.1 It feels like it’s trying to progress the arc of the story, while still leaving enough un-finished for there to be a properly conclusive sequel — to the degree that the “ending on a cliffhanger” doesn’t actually add much more “well, guess I need to read the next one to see how this ends” than the book already had.

Still, there’s a lot of fun worldbuilding going on — an actual proper treatment of what the United States is like in this magical world, unlike Rowling’s utter disregard for… our entire culture, really.2 It honestly leaves me wanting to see other countries in this world, as well. Anglocentrism fits something that started as a Harry Potter parody, but now that we’ve established that Magical Britain is Britain and Magical America is “America, but more libertarian”, I’d love to see, like, Magical Brazil. Magical China. Fill out the world a bit more — what sort of international laws are there governing magic? How does the rest of the world deal with the fact that the Magical United States has no government, and the only thing keeping magic from going viral is that all the magic-users are secretive by nature? Lord knows that won’t last.

I’ll wrap up my rambling here, though. It’s an alright book; I think my main issue with it is timing. If I’d been able to go through all three in the series in a row, I suspect I would’ve enjoyed it a bit more — there’s a lot of set-up for the next book, but now, instead of getting to carry right on to the pay-off, I’m just stuck waiting. So, y’know, maybe wait until next year, but then read it.

  1. Literally so: there’s a third book in the series, scheduled to be released next year, which is explicitly billed as “the third and final book in the Simon Snow series.”
  2. The Fantastic Beasts film actually did an alright job of portraying my country, it feels like, but every aspect of the magical school she tried to describe as our equivalent to Hogwarts is extremely “I don’t get America.” We don’t do school houses, and you really think we’d have a single school? (I must admit, I really love watching Europeans be utterly unable to grasp just how big the US is.)