Zhenyi Tan And a Dinosaur

Weird Safari Extension Bugs

There are 2 Safari extension bugs that drive me nuts when doing customer support. (Well, more than 2, but these 2 are the most notorious lately.)


1. Extension Activation Issue on iOS

On iOS, after turning on the Safari extension in the settings and granting it permissions to access web pages, the extension may still not be active in Safari.

How to Fix:
Open Safari, go to the “AA” menu in the address bar, select “Manage Extensions,” and turn on the extension again. On the webpage where the extension is supposed to work (e.g. youtube.com for Vinegar, search.yahoo.com for Lucky), if the extension’s icon is blue, it means the extension is active. Otherwise, it’s not.

If you see a warning sign like this ⚠️ beside the extension’s name, it means it still doesn’t have the necessary permissions. Tap it to grant the permissions.


2. Extension Deactivation After OS Update

When updating the operating system, there’s a chance that your Safari extension will be turned off.

How to Fix:
Go through the setup process again.

Launch: Lucky Notes

A little while ago, I launched the Lucky app. It turns the Google search results page into “ten blue links.” It also removes tracking and lets you block spammy domains.

There’s a problem, though. Since the search engine doesn’t know who you are, it can’t personalize the search results for you. This means the results might not be as relevant because they aren’t tailored to your interests and past behavior.

Typically, “personalization” means doing some creepy shit, like sifting through your personal data, building a profile of you, and then using algorithms to figure out what you might want to see.

My solution is very stupid. I made an app that lets you save text snippets. So when you search, Lucky will also search through your saved text and include the relevant results. I call this app Lucky Notes.

Remember when we used to blog about new things we learned, so we could easily find them later by googling? Lucky Notes is kind of like that, but it doesn’t involve blogging.

By the way, if you’re interested in blogging again, I have a service you might like. (See, I know how to cross-promote my stuff, too!)

Since Lucky Notes is a simple app, I decided to add a touch of nostalgia. The app uses an old-school font, has a striped navigation bar, and square-ish navigation buttons. The icon is Lucky the cowdog. A cowdog is not the same as a dogcow. They’re very different. Donsumi.


Lucky Notes Pricing

Lucky Notes is available for $0.99 on the App Store. There are no subscriptions, in-app purchases, ads, or tracking. It’s a universal purchase, so once you buy it, you can use it on all your Apple devices.


Lucky Notes Privacy Policy

Lucky Notes doesn’t collect, store, or transmit any personal information.


Lucky Notes Support

If you have any questions, feel free to contact me via email or Mastodon. I read all my emails and Mastodon mentions, but sometimes I’m too socially awkward to reply. Sorry about that in advance.

Launch: Imgpls

I wrote this app to fix a personal annoyance. You probably don’t need it.

I’m not an Imgur user. But in my day-to-day browsing, I sometimes encounter a wild Imgur link. And when I click that link, it takes me to the Imgur website, and the logo loads. Then the app banner thing on top loads. Then I see the popup that asks me to download the Imgur app. Then I have to dismiss the popup to see the image. Then when I try to zoom in, the website loads another image, for some reason.

With Imgpls, clicking links like i.imgur.com/fxBBsLx.gif loads the image directly.


URL Patterns Supported

Imgpls changes URLs with the following patterns:

Imgpls doesn’t change URLs with the following patterns (mostly because they might contain multiple images):


Imgpls Pricing

Imgpls is available for free on the App Store. There are no subscriptions, in-app purchases, ads, or tracking.


Imgpls Privacy Policy

Imgpls doesn’t collect, store, or transmit any personal information.


Imgpls Support

If you have any questions, feel free to contact me via email or Mastodon. I read all my emails and Mastodon mentions, but sometimes I’m too socially awkward to reply. Sorry about that in advance.

Clarifying the Yahoo and Google Confusion with Lucky

Yesterday, I launched Lucky, a Safari extension that removes the clutter from Google search results. Many people are confused by the setup instructions, so let me explain:

I thought Lucky improves Google search? What does this have to do with Yahoo?
Lucky fetches Google’s results and shows them on Yahoo. The specific webpage doesn’t matter, I could’ve used any site. I could’ve used zombo.com. Yahoo is just a vessel to display results from Google.

Can’t you just make Lucky work on google.com?
You might still want to access the original google.com for things like searching for flights, hotels, sports scores, or solving math problems. These features aren’t available with “10 blue links.”

Why do I have to set my default search engine to Yahoo?
This allows you to search with Lucky directly from the address bar. It’s similar to how DuckDuckGo used to work before it was an option in Safari.

I’m still confused. So whose results am I seeing? Google or Yahoo?
You’re seeing Google’s results.


Additional Issues

Aside from the Yahoo-related questions, there are a few other issues that users have encountered:

I live in the EU and Lucky seems to be flaky for me.
In the EU, Google sometimes shows a cookie consent page that you have to accept before accessing the search results. This is fixed in Lucky 1.0.3.

My network is being flagged by Google, and I have to solve multiple captchas to access the Google homepage.
Lucky can’t help with that. You should get a refund from Apple.
I tried to solve this by letting you solve captchas in the app and sending those cookies to Google, but it didn’t work well. Sorry I couldn’t come up with a better solution.

Launch: Lucky

Lucky is a Safari extension that removes the clutter from the Google search results page, leaving you with the 10 blue links.

Update: Clarifying the Yahoo and Google confusion with Lucky.

The classic copywriting formula for selling something tells you to start by talking about the problem, then talking about your solution.

So, the problem. Where do I start with the problems in Google search? I feel like I could write multiple posts on this topic. Should I talk about the declining quality of search results? Their monopoly? Or the AI-generated snippets that tell you to eat rocks and put glue on pizzas?

Anyway, the gist is that Google has added a lot of crappy features, and their search experience sucks now. So much so that people have to add “&udm=14” in the URL to get a cleaner search results page. Lucky takes it a step further.

Lucky not only removes the clutter from the Google search results but also removes tracking, lets you block spammy domains, and fixes some of the annoyances with Google search.


Privacy, Filtering, and Annoyances

Lucky clears the existing HTML and recreates the search results page from scratch. The final page is free of JavaScript. This removes all forms of JavaScript-based tracking and the redirect thing Google does to track you when you click on a search result.

Now, removing the clutter alone won’t improve search result quality. We still need to filter out those SEO spammers.

A few years ago, I made an app to filter search results, but the swipe-to-delete gesture didn’t work well because Google kept changing their HTML. With Lucky, I’m writing the entire HTML from scratch, so it made sense to bring this feature back. The block list is now backed by CloudKit, so it syncs across all your devices.

Lucky uses an old-school pagination footer instead of infinite scrolling. Infinite scrolling made sense when search results were accurate, and you didn’t need to return to the search results page often. But now, I often find myself dissatisfied with the results, go back, and get thrown to the top of page 1.

Google doesn’t use the standard method for switching between light and dark modes, possibly to support older browsers. But their dark mode is so buggy that I often have to refresh the page several times for it to work.

There’s a weird bug (video) with Google where I’d search for something, click on a result, go back, and the search results page would flash for a second before switching back to the destination page. This causes the tab to hang, forcing me to open a new tab to continue my search.


Miscellaneous Features

Even though web extensions are written using JavaScript, I don’t want any JavaScript on Lucky’s results page. There’s no search bar on Lucky’s page because you can search directly from the address bar, which already supports search history and autocomplete.

Lucky fetches Google’s results and shows them on Yahoo. This way, you can fall back to the unmodified Google if needed. It also means Lucky can’t access the content of google.com, which might make some of you feel more comfortable.

Sidenote: I know there are many alternative search engines out there. There’s Kagi, which uses Google’s results but costs $5/month for 300 searches. Then there’s DuckDuckGo, which uses Bing’s results. Sometimes, DuckDuckGo is slow for me, and I have no idea why.


Lucky Pricing

Lucky is available for $2.99 on the App Store. There are no subscriptions, in-app purchases, ads, or tracking. It’s a universal purchase, so once you buy it, you can use it on all your Apple devices.

Lucky isn’t for everyone. If you’re happy with Google or prefer Kagi/DuckDuckGo, you might not need it. But if you’re unhappy with Google and still want an air-gapped way to use it, give Lucky a try.


Lucky Privacy Policy

Lucky syncs your block list through iCloud. When you search, Lucky sends your query to Google. Other than that, Lucky doesn’t collect, store, or transmit any personal information.


Lucky Support

If you have any questions, feel free to contact me via email or Mastodon. I read all my emails and Mastodon mentions, but sometimes I’m too socially awkward to reply. Sorry about that in advance.

Launch: Vinegar 3

Today, I’m launching Vinegar 3, a major small update to Vinegar. This update introduces a new extension, Vinegar Extract.

Vinegar Extract does what the original Vinegar does—it replaces the YouTube video player with a <video> tag. But it doesn’t block ads. So, you’ll need to use it alongside an adblocker or a YouTube Premium subscription.


Why?

I’ve been keeping an eye on the YouTube anti-adblock situation for some time. In fact, to prevent Vinegar from being blocked by YouTube, I’ve already had to rewrite it twice.

I’ve found that when Vinegar is used with other extensions, adblockers, or even VPNs, it can sometimes cause issues. But these issues aren’t caused by Vinegar itself.

Sometimes, YouTube returns 403 errors when you try to load videos using their API. This can make some videos unwatchable. When this happens, I have no choice but to fallback to the ad-laden videos on the YouTube website, which isn’t ideal.

So, thinking about all these problems, I’ve decided to focus on what Vinegar does best—transforming the YouTube video player. As for blocking ads, I suggest using dedicated adblockers. They’re better equipped to keep up with YouTube’s constant changes. This way, I can focus on making Vinegar better, and the adblockers can handle the rest.


Which Adblocker Should I Use?

There are many good adblockers out there. uBlock Origin is probably the most capable, but it’s not available for Safari. So, AdGuard (Mac, iOS) is a good alternative since their filter lists are pretty much the same.

If you’re already using an adblocker, it should work fine, too. Just make sure it’s updated with the latest anti-anti-adblock filters.


What about the Original Vinegar?

Don’t worry, I’m not removing the original Vinegar extension. When you install the app, you’ll see both extensions. If the original Vinegar extension works for you, you don’t have to switch to Vinegar Extract. You can pick the one that works best for you, just don’t enable them both at the same time.

But due to the issues I mentioned, I might be gradually reducing support for the original extension.


Vinegar was launched in 2021. Now, Vinegar 3 is here as a free update. I hope you find it useful. I think this update will ensure the longevity of Vinegar.

Gibberish Is Now Available on TestFlight

This post first appeared on my Gibberish blog.

Gibberish is a blogging app that looks and feels like a messaging app. It’s a bit weird, but that’s the point. This UI tricks my brain into writing mode, just like when I write long messages to my friends. Here’s what it looks like:


Thoughts and Posts

In Gibberish, drafts and published posts are called Thoughts and Posts. When you think of something, create a Thought. You don’t even need a title. As your thoughts build up and start to look like a blog post, you can edit and post them. The shape of the bubbles changes too—they look like thought bubbles in a Thought, and chat bubbles in a Post.


Chrome is Good

Many “minimal” text editors hide the chrome (lowercase) in the writing screen to help you focus. But for me, it didn’t help. It gave me a writer’s block. I propose the opposite: the more chrome on the screen, the smaller the text input field is, the more users are willing to type text in them. Typing in a giant blank screen feels like a chore. But typing in a tiny text field feels effortless.


Miscellaneous Info

There’s a Mac app! It’s not an Electron app, and it’s not a Catalyst app based on the iPad version. I even backported Gibberish to iOS 16 and macOS 12 Monterey.

There’s also a web app if you like that sort of thing. The web app works well on mobile too.

Gibberish supports sync in the traditional sense of the word. It means you can write your posts when you don’t have an internet connection, let it sync, then see your posts appear on the web, just like they’re supposed to.

The app icon is a (chonky) fleuron.


What about Feature X…

“What about scheduled posts?” This question helped me decide which direction to take Gibberish in. Implementing scheduled posts isn’t hard. But if I do that, do I also want to implement features like analytics, multi-author support, or email newsletters? What about social media integration, built-in SEO tools, or a plugin ecosystem? At that point, you might as well use Wordpress.

Gibberish doesn’t have those features, it’s meant to be easy to understand. I want my users to use almost all of the features in Gibberish, not just 10%. Users are supposed to click around the Gibberish app, look at the post information etc, and ask, “Is that all?” That’s a good thing.


Gibber.blog and Pricing

Gibberish is now available on TestFlight. It’s not in the App Store yet, but I’ve thought about the pricing. The app will be $0.99. I don’t want to make it free because it attracts unwanted 1-star reviews. You can use it as a private tweetstorm note-taking app.

Gibberish is available for $0.99 on the App Store. It’s a universal purchase, so once you buy it, you can use it on all your Apple devices.

If you want to publish those posts on the web, you can do so at gibber.blog for $5/month. If you’re interested in trying Gibberish, please send me an email or DM me your email on Mastodon. I’ll send you an invite to the beta.

Random SwiftUI Complaint #123

SwiftUI can be really annoying when you try to do basic UI customization. Consider this list:

🙂

Let’s say you want to get rid of the left padding of the separators. After some googling (which is another problem because Google thinks you want to remove the separators completely), you find the .alignmentGuide modifier with .listRowSeparatorLeading. So you add the code:

.alignmentGuide(.listRowSeparatorLeading) { _ in
    -100 // set it to -100 just to be safe
}

But the navigation bar’s separator still has the padding:

😓

You don’t want to switch to .listStyle(.inset) because that would remove the navigation bar’s separator. After more googling, you find nothing useful. But setting .toolbarBackground to .visible will make the separator full-width. So you add the code:

.toolbarBackground(.visible, for: .navigationBar)

The navigation bar now has an off-white background color, but you can live with that. The separator seems to be full-width!

… until you pull down the list:

🫠

After even more googling, you cannot find any way to remove the left padding of this first separator. The closest thing you can do is to use a .listSectionSeparator modifier to hide it. So you do that:

.listSectionSeparator(.hidden, edges: .top)

Of course, the “real SwiftUI way” is to not remove the left padding of the separators. But sometimes you just want things to look a certain way, right? And that’s where SwiftUI can really, uhh, test your patience.

Launch: Unprocrastinator

Unprocrastinator is a Safari extension that makes you wait 30 seconds before you can see some websites.

Welcome back to my regular program of making weird apps.

Lately, many platforms have turned, uhh, not-so-nice to use, and a lot of people are saying they want to stop using them. Now you can do just that with Unprocrastinator. Unprocrastinator puts a 30-second delay on your chosen websites. It’s like a mini time-out for your brain before you dive into the internet rabbit hole.

This idea comes from an xkcd comic:

After years of trying various methods, I broke this habit by pitting my impatience against my laziness. I decoupled the action and the neurological reward by setting up a simple 30-second delay I had to wait through, in which I couldn’t do anything else, before any new page or chat client would load (and only allowed one to run at once). The urge to check all those sites magically vanished—and my ‘productive’ computer use was unaffected.

The 30-second delay is not customizable on purpose. It’s long enough to be a little annoying, but not so long that you’ll want to turn off the extension right away.

Note: When you first use Unprocrastinator, try not to add too many websites all at once. It could end up being more frustrating than helpful.


Unprocrastinator Pricing

Unprocrastinator costs $0.49 on the App Store. (I’m trying out the new App Store price points.) It does not include any subscriptions, in-app purchases, ads, or tracking. It’s a universal purchase, which means once you buy it, you can use it on all your Apple devices.


Unprocrastinator Privacy Policy

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


Unprocrastinator Support

If you have any questions, feel free to contact me via email or Mastodon. I read all my emails and Mastodon mentions, but sometimes I’m too socially awkward to reply. Sorry about that in advance.

Youtube’s Anti-adblock and uBlock Origin

Recently, YouTube has been ramping up its anti-adblock effort, and I’ve been watching this closely. This blog post is where I write down what I know.


Some Background

Here’s how adblockers (used to) block YouTube ads. Before playing a video, YouTube would check its API, and the server would send back something like this:

{
  "video": "something.mp4",
  "ads": [ad1, ad2, ad3],
  "etc": { ... }
}

And the adblockers would override JSON.parse and Response.json to make it return this instead:

{
  "video": "something.mp4",
  "ads": [],
  "etc": { ... }
}

This trick worked for a few years. But earlier this year, YouTube started making fake requests to see if the responses were changed. If the responses were changed, it meant the user was using an adblocker.

Most adblockers stopped working, but a few like uBlock Origin and AdGuard updated their filters to avoid these fake requests. Then YouTube would update their fake requests so the adblockers would fall for them. It’s been a game of cat and mouse between YouTube and the adblockers ever since.


The Tech Support Hell

YouTube isn’t rolling out the anti-adblock to everyone. It seems to depend on things like your account, browser, and IP address. And if you’re not logged in or you’re in a private window, you’re safe. As a result, there are a bunch of people saying, “I use XYZ and I haven’t seen an anti-adblock popup yet,” unknowingly spreading misinformation.

But here’s the thing: YouTube isn’t just targeting adblockers. Use Privacy Badger? You’ll get flagged. Use Malwarebytes? You’ll get flagged. Set your Edge browser’s tracking protection to “strict”? Yep, you’ll get flagged. So a lot of people think their extensions are safe to use, but actually they’re not.

And contrary to what you might think, using multiple adblockers can actually make things worse. That’s because all your adblockers need to be up-to-date to dodge YouTube’s detection.

As you can imagine, this is creating a tech support nightmare if you’re part of an adblocker team.


The Redditors

On Reddit, the uBO team put up a detailed post on how to handle YouTube’s anti-adblock. But many people don’t actually follow it. You’d see people saying, “I did what the post said but I’m still having issues.” But when they’re asked to share their system info for troubleshooting, it turns out they didn’t really follow the post.

Then there are non-tech-savvy users looking at the post and saying, “This is too complex. I give up.”

Then there are tech-savvy users who say, “Your filter has CODE in it. That’s risky. Can you explain what it does? I don’t want to run anything I don’t understand.”

And of course, there’s always the classic “IVE TRIED EVERYTHING AND NOTHING WORKS HELP!!!!

All this noise makes it hard to find any useful info.


The Stupid Filters

Some people have been sharing custom filters that use CSS to hide the popups. But that’s like sticking your head in the sand. Because the popups don’t stop there: first, it’s just a friendly warning, then you can only close the popup after a delay, then you get a “three strikes and you’re out” popup. And finally, no more popups are shown, but at this point, you can’t play videos anymore.

Recently, someone shared a filter on Twitter that literally had code to set adBlocksFound to 0. It’s as if they think YouTube’s anti-adblock works like this:

if (adBlocksFound > 0) {
  blockUser(); //!!!!!
}

That tweet got super popular. And it probably led a lot of people to add those filters to their adblockers. This has really piled on the work for the troubleshooting team. Did the person who shared it not realize it was harmful? Or did they just care about getting likes?


The Script ID

Every time YouTube tweaks their script, part of the URL changes. This part is what uBO calls the ID, and they have a webpage that keeps track of the latest one.

But here’s where things get messy. Some people think this ID is what they need to block. Some even suggest ways to automate the process (like, “Why don’t you just block that with REGULAR EXPRESSION?”)

Another issue is that sometimes YouTube pushes out an update that has nothing to do with adblock. But it still changes the ID. Then you get people saying, “The ID changed, why hasn’t this post updated yet???”


The Moderator Who Quit Reddit

All this resulted in a ton of pressure on the uBO team members who were trying to help out in the thread. One by one, I saw them say they’d had enough of the comments and weren’t going to reply in these threads anymore.

And then one of the moderators actually deleted their Reddit account. “The ID in the post wasn’t updated because my mother was hospitalized,” they said.

It’s sad to see them leave because of some drive-by comments — new users who sign up for Reddit, leave their comments, and then delete their accounts without facing any consequences.

Sure, there are people who appreciate what the uBO team is doing. But the hurtful comments leave a bigger mark than the good ones.


The War of Attrition

Since May, uBO has been in a cat-and-mouse game with YouTube. And they’ve shown incredible resilience, especially when you consider that there are only two people on the uBO team dealing with YouTube.

The uBO team members are all volunteers. They’ve gone above and beyond to meet every little request from their users. But there’s a limit to how much they can take. At some point, the constant demands become too much, and they will leave uBO for good. It’s one thing to play cat and mouse with YouTube. It’s quite another to deal with a wave of angry users.

Maybe that’s how YouTube will win this war of attrition.