Jesus wept.

Today’s Apple press release.

(Full disclosure: I am an Apple shareholder. I’m glad their stock is up. But I think this is stupid.)


Update (the next morning): I just have to specifically call out this shot from the promotional materials. Seriously. Think carefully about what we’re seeing here. The woman wearing the “Vision Pro” is interacting with other people over FaceTime. None of them are wearing a big contraption on their faces. And they’re definitely real video, not avatars. She cannot possibly look to them the way they look to her. And, critically, they are definitely not using the product being promoted here.

Combine this bizarre demo with a very far-out launch date (I may be wrong, but I think this is the first time Apple has ever announced a product with a “next year” launch), and the whole thing reeks of the kind of vaporware desperation Apple’s competitors are frequently guilty of but Apple itself almost never succumbs to. “Real artists ship” is the phrase Apple has lived by. I’m not sure they believe it anymore.

Update to the update (that afternoon): So, Brian X. Chen of the New York Times got to try the unit, and it sounds like maybe these actually are digital avatars — or at least the woman wearing the ski googles Vision Pro here would be represented that way to the others. Still. Reading the rest of his first impressions, I am just affirmed in my extreme skepticism of this product. Maybe it’s time to cash out my Apple stock before it’s too late.

Update³ (even later that day): One last thing I want to talk about, since I’m mentioning Apple’s stock so much. Yesterday morning, just prior to the announcement, Apple’s stock was at an all-time high. Immediately as the keynote was beginning (1 PM EDT), the stock began to drop. It’s still very high as of the moment when I took this screenshot, but it’s lost about $5 per share from yesterday’s moments-before-the-keynote peak. Hmm.

Chick Corea on the 8’s

After 30+ years, I’m trying to give this album another chance. (It’s not on Apple Music so I had to find it on YouTube.) I bought this album in high school after I joined jazz band and wanted to learn more about the genre. But I really did NOT like it, so I sold the CD, and haven’t heard it since.

I remember liking Chick Corea’s playing and John Patitucci’s bass, but I thought the synth tones were cheesy, the snare drum was mixed way too loud (I still think that), and I didn’t really care for either Frank Gambale’s guitar or Eric Marienthal’s sax.

Listening now… well, I think it’s much better than I remember it being, even if some of it does sound like it should be playing on the Weather Channel’s “Local on the 8’s.”

A simple way to add responsive (breakpoint-specific) blocks in Gutenberg

The new WordPress Block Editor (a.k.a. Gutenberg) has improved immensely over the years, to the point where I am now willingly (although occasionally grudgingly) using it as my main development platform for client sites.

One area where it really falls down though is in smartly handling responsive breakpoints. There is some effort to make it responsive-friendly (though it’s definitely not “mobile first”), but there are really weird holes, like the fact that there’s no built-in way to apply consistent left and right margins on text content at smaller screen sizes; once you’re below the defined content width, if you don’t manually configure your theme to add padding/margins to headings, paragraphs, etc., and they don’t have a defined background color, the text will bump right up against the edges of the screen.

That’s not the problem I’m here to solve at the moment, however. Instead, I want to focus on a handy little tool I’ve been using in my WordPress development for over a decade: specialized CSS classes to designate blocks of content as only appearing on phones, or not appearing on phones.

By “phone” here I just mean the smallest standard breakpoint. I’m using the WordPress convention (at least it used to be the WordPress convention; I don’t feel like I can trust anything anymore) of setting that at the slightly odd (although even) value of 782 pixels.

What can you do with this? Once you have CSS classes that designate a block as only appearing on phones or not appearing on phones, then you can easily tailor your output to certain screens. Obviously (at least, I hope it’s obvious) this is not the ideal solution; it means you’re delivering HTML content — potentially redundant HTML content — that will not be seen by some users. But nothing in web development is perfect, and this can be a convenient way to get out of a pinch when, for example, you have a very complex desktop layout element that simply cannot be adapted in a usable way on phones. You can just hide that element on the phone breakpoint and, if desired, present the same content in a more simplified way to only phones. (Again… only if you can’t achieve a usable phone experience on the same HTML block via media query-specific CSS.)

OK, let’s get down to it. The first thing you need to do is register a couple of block styles. I am only making these styles applicable to the Group block, because that seems like a logical way to rein it in. Any block can easily be wrapped in a group, so if you need this feature, just do it.

register_block_style('core/group', array(
  'name' => 'no-phone',
  'label' => 'No phone'
));

register_block_style('core/group', array(
  'name' => 'phone-only',
  'label' => 'Phone only'
));

That should go into your functions.php file or wherever in your theme you are defining block characteristics. Ideally it should be in a function that is executed on the init action. Next, you need to make sure you’ve got a custom block style .css file enqueued for the Group block. You can place this wherever is appropriate within your theme; I happen to have a nested assets/css/blocks folder where I put mine. Here’s that bit of code, also for your function that runs on init.

wp_enqueue_block_style('core/group', array(
  'handle' => 'my-theme-core-group',
  'path' => get_theme_file_path('assets/css/blocks/core-group.css'),
  'src' => get_theme_file_uri('assets/css/blocks/core-group.css'),
));

And then in the referenced core-group.css file, you’ll need this:

@media screen and (max-width: 782px) {	
  .wp-block-group.is-style-no-phone {
    display: none !important;
  }
}

@media screen and (min-width: 783px) {
  .wp-block-group.is-style-phone-only {
    display: none !important;
  }
}

Now in the Block Editor, when you switch to the Styles tab when focused on a Group block, you’ll see your new style options:

The “house of cards” approach to development is a “fatal error” in itself

This morning my work of putting out a fire for one client was interrupted by the need to put out a blazing inferno for another client. Specifically, they’re running a big sale on their WooCommerce store, and the site was returning a fatal error.

Turning on debugging, I saw this message:

PHP Fatal error: Declaration of Dhii\\Container\\ProxyContainer::has($key) must be compatible with Psr\\Container\\ContainerInterface::has(string $id): bool

Ugh.

There is so much about this that I hate. Mainly, what is any of it for? I have to question whether any of the developers of PayPal Zettle POS for WooCommerce, the affected plugin, really know either. This plugin suffers from what I call the “house of cards” approach to development. Why write your own code if you can just slap together dozens of packages that already do the things you want? On the surface, that’s great. But the problem is, then you don’t really know what your own software does.

I recognize that this is a necessity in many cases. It’s just not practical to reinvent every wheel. But when your application is structured like this, you may have 6 different kinds of wheels, or wheels made out of other wheels, or wheels that also contain a kitchen sink. As usual, xkcd nails it:


Fortunately, WP_DEBUG let me see exactly where the errors were occurring, and although my 20 years of idiosyncratic PHP development experience didn’t help me to understand what the error meant, this StackExchange post did. I just had to change this:

public function has($key)

…to this:

public function has($key): bool

And then I had to do that about a dozen more times in various other files deeply nested in the plugin’s vendor folder, until the PHP fatal errors stopped appearing.

In the WordPress support forums, I discovered near the top of the list a post from someone else experiencing this same error, and the devs suggested it was probably a plugin conflict. They didn’t seem interested in pursuing the possibility that their own code was broken.

But, then again, it really isn’t their code. And that’s the problem.

I’m not above reproach here. I’m a WordPress developer. I use other people’s code all the time! I even sell a product that is substantially constructed out of other people’s code. But I am very judicious about what does or does not get placed in my vendor folder. And I realize that if something goes wrong with it, it’s up to me to fix it, even if it’s not my code.

Speaking of which… I have some updates to make. Gotta go!

Some perspective on Gutenberg

Today I had to do some work on a client’s site that I didn’t build but have ended up maintaining, which is built from an amalgam of multiple “page builder” plugins, but most prominently, WP Bakery.

I was just explaining to my wife (who is not a developer but who uses WordPress, both Classic Editor and Gutenberg/Block Editor, extensively) what it’s like to use WP Bakery:

“Imagine the most annoying aspects of Gutenberg that you find the most annoying*, then imagine something ten times clunkier, a hundred times uglier, and a thousand times less intuitive. That’s WP Bakery.”

—Me

*Yes I really did, deliberately, say it that redundantly.