Thunderbird is getting good again

I used to be a fan of Mozilla’s email application, Thunderbird, for a long time – even going back to Netscape Communicator days and through the first Mozilla release. Unfortunately, at some point, Mozilla focused on Firefox to the neglect of everything else, and then directed their energies into what at the time felt like sideshows (like Pocket, Mozilla VPN, etc.). What ultimately made me switch away from Thunderbird, aside from growing performance issues, was the lack of a space-efficient three-column view (Bug 213945):

Screenshot of Thunderbird bug 213945 about better three-column layout – opened 20 years(!) ago, and finally closed in March 2023.

However, recently (-ish, 2017), Thunderbird was “spun out” of Mozilla proper and started to reorganize themselves, with a clear roadmap, a plan for funding including donations, new design directions, and a general re-architecture and cleanup of the Thunderbird code base.

For a while, I’ve been trying Betterbird, a Thunderbird fork that prioritized merging UI/UX improvements for end users (see the Betterbird FAQ for a few examples) over endlessly discussing technical concerns. However, many of the core issues remained, so I did not fully commit to Betterbird either.

Now, with the new Thunderbird “Supernova” design landing in Beta, I’ve been back on Thunderbird again for a bit longer and the difference is night and day. There are still some improvements to be made, especially around performance in large mailboxes and virtual views including them, but the current Thunderbird Beta looks and feels much more like a modern mail client: Performance is much improved, the UX looks fresh, there is an option to use Unified Folders, groupware (calendaring, contacts, tasks and chat) have been integrated instead of being relegated to extensions, encryption has been integrated in the core (again, from extensions), and even one of the most useful features for me – dynamically managing email identities, i.e. sender addresses – is now part of Thunderbird core (which I needed a while to realize, and which also triggered me writing this blog post, as I feel that function is not documented well).

So, what’s good?

There was a bug in a few betas that made Unified Folders unusable for me, but that appears to be fixed now as well – I may be staying on Thunderbird for the foreseeable future now! 🎉

Try it out for yourself with the Thunderbird Beta (installs alongside the stable version), or wait until the changes land in the next release – and if you want to support FOSS email, donate to the Thunderbird project!

Ordering options by frequency with hysteresis

(Skip to the horizontal divider for the idea if you don’t care about the context.)

With the continued Twitter chaos (popcorn worthy, in a way), the ActivityPub/Mastodon ecosystem has received a ton of additional attention lately. This includes UI/UX work on both the official Mastodon web UI as well as multiple alternative clients on several platforms. I am currently using Tusky on Android, Ivory on iOS, and both the Mastodon “Advanced” UI as well as [Elk](https://elk.zone/) on the web.

One of the features Mastodon exposes prominently is tagging posts with metadata such as the posting language. Unfortunately, the multilingual use case is rarely well served with the current state these features are implemented in: Most clients let the user set exactly one default language for posting, and offer a long, usually alphabetically sorted, list to pick another option. At least there is usually type-ahead search, but it is still far from a great user experience.

Mastodon itself lets users choose several “content languages”, as in “show me content in these languages”. This setting could conceivably double as a list of languages to pin to the top of the language selector widget, but having a separate setting would be better for flexibility. It also stands to reason that most people will be able to read and understand more languages than they are fluent writing in.

Already, there is a bit of a heuristic in Mastodon mainline, namely that it will set the post language of replies to the language of the parent post, which makes sense for threads. Additionally, English is always pinned to near the top of the list, right after the user’s chosen default posting language (which makes some sense, given the widespread use of English as an international communication language, but then we should also ask about why not Mandarin, or Spanish, etc.).

One UI paradigm that is often employed in similar contexts, and one that has also come up in discussions about evolving the language selector feature, is remembering recently used languages. There are more or less sophisticated algorithms here, for example:

  • Strict ordering by recency – the currently selected language will move to the top of the list and push everything else down one slot. Simple, predictable, but a bit annoying if the user frequently posts in different languages.
  • Static ordering from a selection – Of the many languages supported in the standard, the user gets to choose a subset (e.g. with checkboxes) and those get shown first in the widget, in whatever “natural” order they are normally in (e.g. alphabetically, or by database ID) and that order does not change. The advantage is that the user never needs to scan the list visually – click positions remain the same. The disadvantage is, obviously, that the “natural” ordering may not align with the user’s language use frequency at all.
  • Static, user-defined ordering – Same as above, but the user has a way to define the order explicitly. All the advantages as above, with none of the disadvantages, but the UI is necessarily more complex, both for the users to use and the developers to build and maintain, which makes this less accessible.
  • Simple ordering by frequency – usage is counted for each option, and the options ordered by the frequency of their use, e.g. if I post in English 50% of the time, 45% in German, and occasionally in Dutch, then the list would show English, German, and Dutch, in that order. While this has many advantages, it can take a while for the ordering to settle if the different options don’t have clearly different preferences. There is also a pathological case where people might use several options almost equally, and statistical noise will lead to frequent re-ordering of the options, and the case where at different times of the day (or one’s life) one interacts with different communities more or less, in different languages (one simple example could be moving to a new country).
  • Order by frecency. Wikipedia says “In computing, frecency is any heuristic that combines the frequency and recency into a single measure.” The most popular example is probably most browsers’ URL input boxes – I know for a fact that Firefox uses a sophisticated frecency algorithm, but I would assume that other browsers do as well. Basically, this algorithm weighs recently used items higher than they would be looking purely at the frequency of their use. A good compromise for most use cases, but for simple items like languages (versus suggested web URLs after a partially typed query), the ordering will likely be unpredictable and opaque for most users, which would be frustrating.

Now, what originally prompted this post was an idea I had while proposing changes to the language selector in Elk: Currently the default post language is the UI display language (not a good choice, they should really be decoupled) and there is no way to configure post language separately. Additionally, the language chooser widget does not show the currently selected option without clicking. All in all, not a great user experience (but one that is common in lots of software, especially when it is developed by a primarily English-speaking group). However, I wanted to make sure that they wouldn’t switch to a simple frequency-based model, because I post almost equally in English and German and I hate nothing more than drop-down menus that rearrange themselves seemingly randomly.

After considering the options outlined above, I thought that maybe another sorting method would be useful, which I admittedly haven’t completely thought through yet, but that I’d like to call “frequency (or frecency) with hysteresis“.

The idea is simple: Instead of looking only at frequency or frecency of items, add a hysteresis threshold.

Hysteresis, in this context, is at its core a “lagging change”, an approach commonly used for e.g. temperature control: Instead of stopping heating exactly at reaching 21.0 degrees C and restarting heating immediately when the temperature falls to 20.9 degrees C, there is a certain window the measurement has to clear first, so the heating would only start at e.g. 20.0 C and then heat up to 21.5 C, instead of constantly flip-flopping between on and off around 21.0 C.

In the context of ordering items in a menu, that would mean that the items do not get re-ordered immediately when their frequency or recency ranking changes, but only after it has changed by a certain amount (or amount of times).

An example: Of my last 10 posts, 5 were in English, and 5 in German. The languages drop-down shows English, German, and then all other languages, because I used English last. Now I post once in English and once in German, and now the ordering would be German, English, others, if going by frequency with last-used-wins. Annoying, because chances are good that the next post would be in English, which is now option #2.

If there was a hysteresis to the ordering, it would not change until I’ve posted significantly more in one language recently, let’s say at least a third more than the previous top spot = German gets the new top spot only once I posted 2 more times (in the above example) in German than English (6/3=2, 6+2=8). The exact thresholds should be determined based on some actual usage data, but this could nicely work around the challenge of people using multiple items with near equal frequency, and avoid the flip-flopping of a simple recency-based approach.

Finally some good headphones

Valco VMK20 headphones in open packaging

I might have finally found a set of headphones that I actually enjoy the sound of, that have good microphones, and that I can wear for hours on end without my ears slowly deforming and then dying, and I thought I would write my experiences down to maybe inspire someone else to get better headphones.

NB: None of the below links are affiliate links, but I am happy to send you some if you want.

As far as over-ear headphones go, I recently got and instantly fell in love with the Valco VMK20 Wireless Headphones. I have to admit, I was sniped by an actual ad, which hasn’t happened in quite some time, but their Finnish charm and self-deprecating humor got me, so I figured I’d check their claims and otherwise yell at their CEO. Surprisingly, the headphones are actually as good as described! Funny how things go if there’s no gigantic marketing spend in front of a smaller but formidable controlling department!

For in-ears, I was using the Turtle Beach Battle Buds for a while for video conferences and voice chats, and that was ok, but they’re wired and the fit isn’t too great – but you can replace the microphone with an awesome one if you are so inclined. But the big breakthrough came with the TRN V90 that I got on AliExpress for something like 25€. What can I say, the sound is simply amazing, the fit is great, the pre-formed wire loops keep the headphones in place even during a workout, and the seal is good enough to make the world quite quiet. They are wired out of the box, but you can just connect them to one of the many Bluetooth cables (sic!) the manufacturer offers. I picked the TRN BT3S with the neck loop, because I like looking like a huge nerd. By simply switching the cable for the Bluetooth module, the headphones gain Bluetooth 5.0, aptX, and a CVC6 microphone. The V90 are a teensy-tiny bit “thicker” on the bass end than I’d normally like, but it’s never distracting or overpowering. And they’re comfortable enough to wear when lying down as well.

Are those the best headphones ever? I don’t know, I only tried maybe 40 or so.

If you only have two ears, why do you need so many headphones?

The simple answer is that (almost) all headphones suck, and headphone companies constantly overpromise and underdeliver, especially if you’re, like me, part of an apparently tiny group of people that just wants straightforward, clear sound and ideally a good microphone. Instead, the market is full of headphones with eXtreme Bass Boosting, a Bluetooth range of tens of centimeters, Active Noise Canceling that replaces relaxing wind sounds with distressing electronic whistling, batteries that don’t last even a short journey, and microphones that dangle all over the place so they can better pick up the sound your clothes make as you move, or the neighbors five blocks over whispering.

Also, apparently my ears are shaped weird.

Some of the noteworthier headphones that I tried:

The BOSE QC35 II, which I finally gave in to buying about midway through my career in consulting (where literally everybody had them, or the predecessor, the QC25), were pretty nice: When I got them, they had some of the best ANC on the market, the sound is good enough, they’re lightweight and they have a built-in mic. However, the sound could be better, the ANC could be better (and newer models by e.g. SONY make this very obvious), the microphones could be a lot better (for a long time, I was wondering how some people on phone conferences had such amazingly bad call quality – then I tried using the QC35 for calls: the moment the phones go into headset mode, the mic strains to pick up even the faintest or far-away sounds, which it will then amplify and feed both into your call and into your ears, giving you super-hearing and the other participants in the call tinnitus). They still have a certain status attached to them, but to be honest, I would rather have better quality build & sound, and I am also not a fan of BOSE’s app strategy, where they try to trick you into letting them track you, and shit. All in all, not unhappy with the purchase, but glad I did get them at a discount.

The OneOdio Pro-10 Over-Ear were recommended by the Sendegate forum, because they come with a microphone which can be detached and replaced by the – very good for its price-point – V-Moda BoomPro. This indeed makes them into a great headset for podcasting or recording spoken audio, but the size and fit of the earmuffs combined with the pressure the headband put on my ears makes them very uncomfortable to wear for extended periods of time. Your mileage may vary if you are not wearing glasses or have a different head or ear shape, and the price point is low enough to just try them out.

There were a bunch of others, like the Anker SoundBuds Flow (quite liked them, but mic wasn’t great), Sennheiser buds that I already forgot the name of, a few no-name “moderator headsets” with proprietary connectors that I had to file down or resolder (but then the mic quality was quite good), the Anker SoundCore Strike 1 gaming headset (which is surprisingly comfortable and has a pretty good, detachable mic, but is way too bulky to use outside of gaming/streaming), some Mobvoi headphones I got tricked into buying after I got my Mobvoi smartwatch which I also didn’t like, some “Zircon” headphones that I don’t even remember buying, the Superlux HD 681 (which everybody knows, I think, but if not, they’re a high quality replica of high-price headphones that shall be unnamed – good, but half-open doesn’t cut it everywhere), the Sony MDR-7506 (which I still think are amazing but I rarely feel like using wired headphones anymore), the ATH-M50X (which I liked for their portability until the headband and padding crumbled and Audio-Technica did not manage to provide replacements…), the RHA MA750i (very nice sound, very good support, but ultimately not reliable enough for me to stick with the brand at increasing price-points), and others.

How to change the default branch name for `git init`

When a new Git repository is initialized using git init, the default name of the main branch that is created is “master” (likely based on the terminology used in BitKeeper, which Git was created to replace).

Update Nov 2020: This is now the default in Git.

For the past 20+ years, the usage of “master/slave” terminology has been criticized as needlessly reproducing racist terminology of slavery, and in the course of 2020, this discussion has finally broadly reached Git as well, with calls to rename the default branch to “main” or “trunk” instead (previously, this had been proposed for specific projects, e.g. GNOME in 2019).

Petr Baudis, who picked the names way back in 2005, weighed in to state that they wish they had picked “main” instead. Using “main” instead of “master” has the benefit that it autocompletes with “m” and “ma” as well, and is also the term GitHub (who still collaborate with ICE) are switching to.

Currently, the branch name a new repository is initialized with is hard-coded in Git, so there are two options to change the default (to “main”, in the following examples):

  1. Changing the HEAD pointer before the first commit, using the symbolic-ref subcommand: git symbolic-ref HEAD refs/head/main or manually overwriting the .git/HEAD file: echo 'refs: refs/head/main' >.git/HEAD;
  2. Putting this change into a git template, by copying the default git template: cp -r /usr/share/git-core/templates ~/git/template, adding the ref pointer: echo 'ref: refs/heads/main' >~/git/template/HEAD, and passing that directory to git init in the --template= option (or setting init.templateDir).

If you want to easily change the main branch name of existing repositories, you can just run git branch -m master main && git push -u origin main. Remember to adapt any settings or scripts that might refer to branches by name, such as CI/CD, “protected branches”, etc.!

Calling all audio and hardware hackers!

I am part of c3lingo, a community of interpreters offering simultaneous translations at cultural and social events such as Chaos Communications Congress and Camp, Fusion Festival, TIN-Solifest and others.

The project has been running for many years, but especially since we are increasingly active outside of C3, we have some hardware challenges as there is often no pre-existing infrastructure and/or little budget for hardware.

That’s why we want to build our own interpreting consoles that are as open and free as possible, inexpensive to buy, and customized to our use-case.

I am looking for more information and support with knowledge, tips, and also active help with planning and construction. More details below.

Continue reading “Calling all audio and hardware hackers!”

BIGINTs in rails as primary keys

(This is an update to my older post on bigints in rails migrations.)

BIGINT columns in rails have always been a little annoying to work with, which is why I published a blog post on how to do it, five years ago, to serve as a reminder to myself and as a resource to others. BIGINT primary keys were even more hit-and-miss.

Enter Ryuta “kamipo” Kamizono, who took to improving rails’ support for this, created a pull request “Allow limit option for MySQL bigint primary key support,” and landed that in rails:master last month, which allows you to write things like this:


create_table :foos, id: :primary_key, limit: 8 do |t|
end

# or

create_table :foos, id: false do |t|
  t.primary_key :id, limit: 8
end

The patch should be included in the next release of rails. Happy hacking!

Integer vs to_i in Ruby

Since this has recently come up in a work context, I would like to take this opportunity to remind everyone to always specify the expected base when trying to convert strings to integers using Integer(value), because as opposed to String#to_i, the Integer(…) constructor does honor prefixes like 0 for octal, 0x for hexadecimal, etc.

Example:


Integer("0462011540000077")  #=> 21029460115519
Integer("0461990540002606")  #=> ArgumentError
"0462011540000077".to_i #=> 462011540000077
"0461990540002606".to_i #=> 461990540002606
# now, specify the base explicitly:
Integer("0461990540002606", 10)  #=> 461990540002606

The same thing happened with JavaScript’s parseInt and bit lots of people, so: cover your bases.

Ruby documentation for Integer()

Keybase

Keybase ist ein neues Projekt von Max Krohn und Chris Coyne (die vorher u.a. OKcupid gegründet haben). Es will ein besseres Verzeichnis öffentlicher Schlüssel sein.

Eines der Probleme an sicherer Verschlüsselung im Moment ist, dass die meisten Verfahren asymmetrisch sind. Jeder Nutzer hat also einen geheimen und einen öffentlichen Schlüssel, und um eine Nachricht zu verschlüsseln, brauche ich meinen geheimen Schlüssel sowie den öffentlichen Schlüssel der Empfänger. Damit entsteht aber auch die Problematik, dass ich irgendwie an den richtigen Schlüssel kommen muss, bevor ich einen sicheren Kommunikationskanal mit dem Empfänger aufgebaut habe, denn sonst könnte mir jemand einen falschen Schlüssel unterjubeln und meine Kommunikation abfangen.

Bei OpenPGP/GPG versucht man, das Problem durch das sogenannte „Web of Trust“ zu lösen: Man kann anderer Leute Schlüssel mit einem Vertrauensmarker signieren und so angeben, wie sicher man ist, dass der Schlüssel zur Identität passt. Das reicht von „keine Ahnung, nicht geprüft“ zu „ich habe den Schlüssel von der Person direkt bekommen und seine Identität geprüft“. So baut sich ein Vertrauensnetzwerk auf, wenn ich A vertraue, der wiederum B geprüft hat, und die wiederum C kennt. Nichts hindert jemanden daran, massenhaft Schlüssel unter falschen Identitäten zu erzeugen und zu verteilen, es ist aber unwahrscheinlich, dass diese vertrauenswürdige Signaturen bekommen. (Interessant wäre allerdings mal, ein komplett eigenes Web of Trust mit tausenden falscher Identitäten anzulegen, die sich gegenseitig plausibel vertrauen.)

Keybase will dieses Problem nun lösen, indem sie Identitäten bei Dritten wie z.B. Twitter oder Github kryptografisch bestätigen lassen: Ich als Besitzer meines geheimen Schlüssels signiere ein kurzes Codewort, dessen Integrität Keybase mit meinem öffentlichen Schlüssel prüfen kann. Damit kann ich mathematisch sicher beweisen, dass ich z.B. den Twitter-Account @moeffju kontrolliere und dieser Account zu dem angegebenen öffentlichen Schlüssel gehört. Twitter wird somit quasi als Web of Trust verwendet.

Bei Keybase, das noch in der Alpha ist, will man noch weiter gehen: Nicht nur der öffentliche Schlüssel wird zugeordnet und Identitäten bestätigt, man kann auch den geheimen Schlüssel verschlüsselt zu Keybase hochladen und dann im Browser Nachrichten signieren und verschlüsseln. Ich rate davon ab, das mit dem eigenen Hauptschlüssel zu machen – Verschlüsselung im Browser kann zwar sicher sein, aber nicht vertrauenswürdig. Keybase muss nur anderes JavaScript ausliefern und schon kann es potenziell auf den geheimen Schlüssel zugreifen. Mit einem Unterschlüssel kann man es eventuell machen, sollte sich aber der Risiken bewusst sein. Sicherer ist es, den Kommandozeilenclient auf dem lokalen Computer zu verwenden und seinen geheimen Schlüssel gut geschützt aufzubewahren.

Wer Keybase ausprobieren möchte: Ich habe drei Invites, die ich an kryptografisch versierte Benutzerinnen verteilen möchte. Schreibt mir kurz, welche Erfahrungen ihr mit Verschlüsselung bisher gemacht habt und wieso euch Keybase interessiert. Bonuspunkte, wenn ihr eure Nachrichten mit eurem PGP-Key signiert (und eure Key-ID angebt).