Kartones Blog

Be the change you want to see in this world

Toggling Firefox dark mode via bash script

It might be just me, but all this dark theme trend, while really nice and an advancement over past attempts (I used Windows with a black theme long ago and was hard for anything other than a gaming-only computer), feels still not perfect: My Ubuntu 20.04's dark theme has an almost white notifications & calendar widget, some applications don't support it, but where I find it still inconsistent is regarding browser support; MS Edge will use the same operating system setting, and Firefox allows fine-tuning for the theme (window borders, etc.) but for the actual browsing it's a config setting of either on or off.

The property I'm talking about, as of Firefox v89 is "ui.systemUsesDarkTheme", with integer values 0/1 for disabled/enabled. And you can only change it from the advanced settings, from about:config.

That this is what I desire:

  • Operating System: Always dark theme ✓
  • Browser theme: Always dark theme ✓
  • Browser tabs dark theme detection/preference: Switchable on demand ✗

If I could have one of the following regarding the last point, I'd be happy:

  • A button to toggle ui.systemUsesDarkTheme values (enabling/disabling it whenever I want)
  • A way to create a javascript bookmarklet to toggle the value (AFAIK for security reasons you cannot change about:config settings via JS scripts)
  • A way to access the property from an extension, to build a "toggle pages dark theme" one (browserSettings looks very limited)

As none of those are available options right now, I did an alternative approach: creating a bash script that will run upon login (and on demand whenever I want), to automatically set the property at my Firefox profile preferences file (prefs.js), depending on the time of the day. It is not perfect, as you have to have Firefox closed or not only won't detect the change, but will also override when closing the value you set with whatever value it had while running, but at least works for me if I set it to run when I login.

Anyway, this is the script:

PROFILE="<your-profile-folder-name-here>"
HOUR=$(date +%H)

DARK_MODE_SETTING=0
if [ $HOUR -gt 20 ] || [ $HOUR -lt 8 ]
then
    DARK_MODE_SETTING=1
fi

sed -i "s/user_pref(\"ui.systemUsesDarkTheme\",.*);/user_pref(\"ui.systemUsesDarkTheme\",$DARK_MODE_SETTING);/" ~/.mozilla/firefox/$PROFILE/prefs.js

Company Employee Turnover Metrics

Motives of course can vary, but usually when a company has significant employee turnover it is due to one of two reasons:

  • Organizational changes (restructuring, saving costs by reducing workforce, ...)
  • Voluntary turnover (people leaving the company)

In both cases, I think it is a good metric for anyone interested in a company, whenever it is to join it, to invest on it, or simply to collaborate with it.

If there were some important restructuring you want to know about it. Did the company had poor management and it changed? Was it because it had to cut costs? or maybe because somebody decided to close a line of products without re-converting employees?

We live in a world where people are often seen as numbers. Even the department in charge of people is called "Human Resources", as if categorized similarly as hardware, transport and other types of resources available to the company. So it often happens that when you need to save money, usually you save some of it by reducing the amount of salaries to pay. I'm not going to dig into if that's always unfair or sometimes justified, just state a fact.

It is also really revealing if you can gather info of employee turnover, specially on the main taskforce. I'll exemplify with a tech company: do engineers, product managers and UX people leave almost every month, or is it instead considered an infrequent event the action of somebody leaving the company? do employees on average stay for many years, or is the rotation high? and if the rotation is high, is it only employees that had been for some time, or also there's a number of new hires that don't last much?

And even more revealing (IMHO at least) could be to weight the seniority of the people leaving vs the senior roles that have been at the company for long. If there's a sudden stampede of senior roles that look relevant for the company, either they are going to build something together, or something smells off. If a place has mostly "fresh" senior roles, what made all that old guard go away?

Again, this might not be bad on itself. Maybe the company was in desperate need of fresh air and change, and the new blood will bring radical new ideas and fix things up. But I think it would always be relevant to know what happened, what triggered that disruption.

All this rant comes because I was thinking the other day about how cool would be to be able to analyze employee turnover, because we have a great source of data... the problem is that it lives inside a walled garden: LinkedIn. Or maybe I should say electrified-fenced, as it is against their terms of use to do any web scrapping (and almost almost all data is not publicly available). It would be great to have an API to fetch, given a company, a few data of its employees, like the role and company tenure. Add to that searching for ex-employees, checking when they left, the role they had and how long did they stayed at the company. Everything else could be anonymized or not even returned, so really is not much of a privacy problem. But LinkedIn APIs are almost useless, and then even the company pages require being logged-in to check, so we have all such valuable information, but we can't explore it.

It's sad how the internet (exceptions like Wikipedia or Archive.org aside) has evolved into a group of huge, closed "information warehouses". Sure most of them are "free" (we pay with our data), but we can only use it in certain, limited ways imposed to us.


ctypes, OpenCV and Pillow

Note: This is a work in progress, consider this post more like some development notes of sources and links and references that I've found interesting. I might throw away half of it, or never finish the experiment.

What do ctypes, OpenCV-python and Pillow have in common, apart from being Python libraries? In my case they form a nice pack to begin tinkering with automation in less usual scenarios... like videogames.

After finding an amazing tutorial on how to teach an AI to drive cars in GTA V with Python, I thought I could start maybe with something simpler. Like an auto-clicker for those idle & clicker videogames.

I am using Pillow because its ImageGrab module is perfect to capture screenshots (with bounding box directly, so no need to crop anything), and it's a single line of code to transform the image into an optimized NumPy array... which is also the source for many OpenCV operations.

Regarding OpenCV, I'm just learning it as I go, half by reading its tutorials and half by directly playing with things I've seen in the GTA V AI article, like changing colorspaces and canny edge detection. I am still toying with which approach is better (grayscale or HSV), but I already have a working prototype that draws edges of coins as a black & white mask, and then by reading pixel data I'm able to pinpoint them in screen.

Handling input is becoming actually the hardest part, as I want to build it for Linux (there are lots of articles on ctypes and Windows DirectInput) and I'm not familiar with the X Window System. Thankfully the X11 library documentation contains all calls and I already have implemented querying the mouse position (XQueryPointer) and moving it to wherever I want (XWarpPointer), so I see where it detects entities better than just raw X,Y coordinates.

I am missing how to send mouse clicks, and I'd like to play with OpenCV a bit more to try to really detect items within it (right now is raw array comparisons).

I don't know if to publish the code, partly to not ease cheating on those games (which in the end you play for free) and party because excepting the input handling code, everything else are really basic operations with each library that you can find on their respective official documentation or tutorials.

In any case, here's one screenshot of a debug frame mask with edge detection. The game was running and already past the equivalent frame, but the goal is to automatically click to pick up all gold coins enemies leave upon dying:

A clicker game and OpenCV edge mask frame


CSS-Only dark mode in 15 lines of code

I'm a fan of dark UIs, and since Apple created the "dark mode" trend it's really easy to implement it. I built a quick implementation for my small RSS reader, and thought I could share how simple it is, because there are tons of articles with loads of code and Javascript and whatnot, but things can still be simple:

  • No Javascript required (this means no toggle functionality, but not a big deal)
  • No complex CSS rules or queries
  • Not a pure black + pure white colors selection
  • Good practices: remember hyperlinks & set a default almost-white image bg (because almost nobody remembers transparent images, except AWS blog posts)
  • Good trick: apply a slight grayscale filter to images, so they aren't that bright
  • Extra: A nice border color (I use Bootstrap at my RSS reader, so for the button and panel borders is nice)

All in 15 lines of code (12 if you don't want the border rule). Also, if the filter is not supported in your browser, will simply render the image normally, so the fallback is original behaviour instead of a degraded experience.

First, the director's cut commented version:

/* Works with Javascript-disabled, and if your browser doesn't supports media queries, it's way too old */
@media (prefers-color-scheme:dark) {
    /* A light-grey-but-not-white and a dark-but-not-pure-black, both stolen from Firefox's dark theme colors */
    body {
        color: #DCD8D9;
        background-color: #2A2A2E;
    }

    /* because browsers usually allow to customize default hyperlink colors */
    a {
        color: #DCD8D9;
    }

    img {
         /* subtle but easier on the eyes instead of full bright */
        filter: grayscale(30%);
         /* good practice: bg color for transparent images, diagrams, etc. */
        background-color: #EEE;
    }

    /* sample of something that has a border */
    div.panel-default {
        border-color: #4C4C4E;
    }
}

And the comment-less 15 lines version:

@media (prefers-color-scheme:dark) {
    body {
        color: #DCD8D9;
        background-color: #2A2A2E;
    }
    a {
        color: #DCD8D9;
    }
    img {
        filter: grayscale(30%);
        background-color: #EEE;
    }
    div.panel-default {
        border-color: #4C4C4E;
    }
}

And that's pretty much it.


Choose Your Own Adventure - Epub Gamebook

I love reading, and one of the things I enjoyed a lot as a child was reading Choose Your Own Adventure books. Well, technically they are called gamebooks, but as many others I tend to generalize the brand name as the book type. In any case, they were really simple books with branching paths and narratives, often with multiple endings.

I already have an unfinished but working project for building web CYOA readers, but as I really enjoy reading at bed from my Kindle, I wanted to do a little experiment: try to build ebooks that have branching paths and act like a classic gamebook.

The idea is really simple: Each relevant page number (as in "go to page XXX") becomes a chapter, and as ebooks support links as references to chapters (and they are trivial to set even with minimal formats such as Markdown), build the navigation based on chapters.

A quick search, reading a bit about Pandoc and using its official Docker image, and I was able to quickly build something: https://github.com/Kartones/cyoa-epub.

The sample generated in the repository is a very simple ebook with few chapters, but serves as a, introduction tutorial on how the metadata works, how to add a book cover (of course you can also have images at normal pages), how to add a table of contents, and a minimal "adventure" sample that puts to the test the approach.

And it indeed works! Here's an almost final version being tested:

Testing the ebook in my Kindle

I now guess if with some OCR and a bit of text cleaning and processing I could build digital versions of those childhood books... 🤔


Previous entries