Zhenyi Tan And a Dinosaur

Rewriting My Toy App in Swift

I’m not launching a new app. I wrote Staring eight(!) years ago.

Staring is a tiny app that prevents your Mac from sleeping. There are many like it, but this one is mine.

The rewrite was… uneventful. Swift saved me a lot of keystrokes, Xcode saved me even more. It suggested I rename NSTask to Process, so I did. There’s now a button property in NSStatusItem so I can delete my custom label class.

The whole thing is just 90 lines of code in one AppDelegate.swift file. You can check out the code if you want to use it as a starting point for your menu bar apps. Or download the app if you, too, like to have a ಠ_ಠ in your menu bar.

How Does YouTube Autoplay Its Videos on iOS?

I wonder if the WebKit team will patch this.

By far the most requested feature for Vinegar is to autoplay the next related video or the next video in the playlist. But Safari on iOS requires a user gesture to play video in a <video> element. More specifically:

The call to video.play() must have directly resulted from a handler for a touchend, click, doubleclick, or keydown event. So, button.addEventListener('click', () => { video.play(); }) would satisfy the user gesture requirement. video.addEventListener('canplaythrough', () => { video.play(); }) would not.

So how come YouTube can seemingly bypass this requirement and autoplay one video after another? I don’t actually know, but I think this is how:

  1. On page load, mute the video and start playing (Safari allows muted autoplay).
  2. When the user unmutes the video, capture the click event.
  3. In the event handler, do this:
    1. When the video ends, load another one and play it.
    2. Update the rest of the web page and the URL dynamically.
  4. When the user clicks on another video, do 3i and 3ii.

It doesn’t matter if your code is in a callback of a callback of a callback. As long as you can trace it back to a click event handler, you’re good. Here’s a proof of concept to show that it even works if you create <video> elements on the fly:

var index = 0;

function nextVideo(oldVideo) {
  let video = document.createElement('video');
  video.playsinline = true;
  video.controls = true;

  if (oldVideo) {
    oldVideo.replaceWith(video);
  } else {
    document.body.appendChild(video);
  }

  video.src = `${++index}.mp4`;
  video.play(); // It works!

  video.addEventListener('ended', (e) => {
    nextVideo(video);
  });
}

// The only user gesture you need
document.body.addEventListener('click', (e) => {
  if (index === 0) nextVideo();
});

Launch: Vinegar

Remember YouTube5? And a Dinosaur remembers.

YouTube5 was a Safari extension back when Flash was still a thing and hated by everyone. It replaced the YouTube player (written in Flash) with an HTML <video> tag.

And now the YouTube player situation has gotten bad enough that we need another extension to fix it. That’s where Vinegar comes in. Vinegar also replaces the YouTube player (written in who-knows-what) with a minimal HTML <video> tag.

Vinegar is commonly used as a household Tube cleaner.

The benefits include:

Vinegar works on embedded YouTube videos on other websites, too. I will consider adding support for other video sites in the future.


Pricing

Vinegar is available for $1.99 on the App Store, with no in-app purchases, no ads, and no tracking. It’s a universal purchase so you only have to buy it once to use it on iPhone, iPad, and Mac. I hope you find it useful.


Vinegar Privacy Policy

Vinegar does not collect, store, or transmit any personal information.


Vinegar Support

If you have any questions, email me or contact me on Twitter.

Vinegar for iOS Is Now Available on TestFlight

Update: Vinegar is out!

Launch: Vinegar for Mac

Update: Vinegar is out!

New in Web Inspector: Updated Layout, Search HTML, and Network Responses

Web Inspector 1.2.1 is out! This is a big update.

Updated layout

I moved all the buttons to the top because hunting for the buttons when Safari’s toolbar keeps appearing and disappearing is annoying.

Also, I moved the Inspect toolbar from the Elements tab to the DOM tab. The new layout should make more sense if you’re used to Web Inspector on the desktop: view the DOM elements in DOM, then switch over to Elements to see its properties and CSS styles.

Also, also: I removed a few redundant (read: useless) buttons.

Also, also, also: on non-mobile-optimized web pages, Web Inspector will scale its UI up so it won’t appear comically small on the iPhone.


Highlight and select

Now that the Inspect toolbar is in a more prominent location, perhaps I should talk about them since many people have never noticed them before.

The Highlight button (second from the left, looks like an eye) toggles the highlighting of the selected DOM element. On desktop, you get the highlight by hovering over DOM elements, but we can’t do that on mobile, so yeah, a button.

The Select button (first from the left, looks like a mouse cursor and a square) is a classic Web Inspector tool. Tap on it to start selecting any items on the web page, and see it in the DOM tree. Web Inspector will temporarily hide the panel while you’re doing this. This button triggers highlight mode. Remember to turn this off if you want to interact with items on the web page again.

The Edit button (third from the left, looks like a pencil) lets you edit the selected DOM element.


Search the HTML

The Search button on the right lets you search the HTML. You can cycle through the search results, and Web Inspector will try to move them (both the item and its representation in the DOM tree) into view. This button triggers highlight mode.


Formatted network responses

There’s a new View Response button on the details page of a network request. You can tap the button to see the prettified, syntax-highlighted network response. It works for HTML/CSS/JS, other text files, and images.


Check it out

Web Inspector is free, with no in-app purchases, no ads, and no tracking. Get it in the App Store today.

Launch: ActiveTab for Safari

If you’re wondering why I made this, read this article by John Gruber.

ActiveTab makes it easier to spot the active tab in Safari on Mac by drawing a line below it. It works by predicting the position of the active tab based on the size of your browser window and the number of tabs.

“The extension [...] undeniably makes it easier to spot the active tab in Safari.” - MacStories
“It’s worth every penny.” - iMore
“ActiveTab simply makes it easier to spot the active tab in Safari.” - MacRumors
“It makes the tab instantly recognizable, even when you’re not looking directly at it.” - Cult of Mac
“It solves the problem of creating enough visual contrast between active and inactive tabs.” - iDownloadBlog
“It’s the latest must-have for Mac.” - Creative Bloq


Note

There’s a bug in Safari that causes web extensions to disappear:

If you’re just looking for a solution to the issue, here it is: quit Safari, copy the following command to the clipboard, open the Terminal app (located in the Utilities subfolder of the Applications folder), and paste the command.

/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f -R /Applications/Safari.app

Pricing

ActiveTab is available for $1.99 on the Mac App Store, with no in-app purchases, no ads, and no tracking. I hope you find it useful.


ActiveTab Privacy Policy

ActiveTab does not collect, store, or transmit any personal information.


ActiveTab Support

If you have any questions, email me or contact me on Twitter.

By the way, let me know if you’re interested in ActiveTab for iPad.

Launch: AMP Shockwave

Filing this under “meh, why not.”

EMP Shockwave!

AMP Shockwave is a Safari extension that redirects AMPs to regular web pages.

There’s no user interface and no settings. It’s just one content.js file with 40 lines of code. I extracted the code from Time Capsule, and it works in my limited use case. If you like simple things, check it out.


Pricing

AMP Shockwave is free, with no in-app purchases, no ads, and no tracking. Get it in the App Store today.


AMP Shockwave Privacy Policy

AMP Shockwave does not collect, store, or transmit any personal information.


AMP Shockwave Support

If you have any questions, email me or contact me on Twitter.

Search Filter Is Now Available on TestFlight

Introducing my latest app, Search Filter! Search Filter is a Safari extension that lets you delete search results from spammy domains.

It’s like a spam filter for search results.

Here’s how it works: Swipe to delete any search results you don’t like. Tap the extension button to see the deleted domains, and recover them if you want.

Once you delete a search result, Search Filter will delete other search results from the same domain, too. Deleted search results will stay deleted in subsequent searches.

I built Search Filter out of my frustration with StackOverflow scrapers, but that’s far from the only use case. You can use it to delete websites that publish clickbait, content farm listicles, or SEO’ed-to-the-death “content.”

Search Filter currently only works on Google, but I will consider adding support for other search engines.

I’m still not sure about the price. How much should I charge for this? $3.99? Free, but with a $0.50/month subscription for syncing your blocklist? Let me know!

Disclaimer: Search Filter is beta software, and it is buggier than your average app. Google’s HTML seems randomly generated these days, and there must be a lot of edge cases that I’ve overlooked.

If you see any bugs (usually in the form of “delete buttons appear where they shouldn’t be”), send me a screenshot and let me know:

  1. the search query
  2. the URL of the search page

If you would like to TestFlight Search Filter, send me an email or DM me your email on Twitter, and I will invite you to the beta.

Launch: Web Inspector for iOS

Web Inspector is now available in the App Store 🥳!

Web Inspector is a Safari extension on iOS and iPadOS that works like its desktop counterpart but is less powerful. It allows web developers to edit web pages on the fly, debug JavaScript, and more.


Pricing

Web Inspector is free, with no in-app purchases, no ads, and no tracking. You can get it in the App Store today. I hope you find it useful 🙏.


Web Inspector Privacy Policy

Web Inspector does not collect, store, or transmit any personal information.


Web Inspector Support

If you have any questions, email me or contact me on Twitter.