Berlin Mobile Hackfest

Last week we had a small hackfest in Berlin, with a focus on making GNOME work better on mobile across the stack. We had about 15 people from various projects and backgrounds attending, including app developers, downstreams, hardware enablement, UX design, and more. In addition to hacking and planning sessions we also had some social events, and it was an opportunity to meet nice people from different corners of the wider community :)

The Event(s)

The postmarketOS gang had their own hackfest over the weekend before ours, and on Monday we had the Cultivation Space venue for some chill random hacking. I wasn’t there for most of this, so I’ll let others report on it.

The main hackfest days were Tuesday and Wednesday, where we had an actual unconference agenda and schedule. We met at 11:30 in the morning at Cultivation Space and then managed to get through a surprisingly large list of topics very efficiently on both days. Kudos to Sonny for coming up with the format and moderating the schedule.

Late night podcast recording on Wednesday (note the microphone in the bottle in the center)

systemd and Image-Based OSes

On Tuesday Lennart from systemd stopped by for a bit, so we had a session with him and the postmarketOS people discussing integration issues, and a larger session about various approaches for how to do image-based OSes. It’s clear that this direction is the future — literally everyone is either doing it (Endless, Silverblue, GNOME OS, SUSE, Carbon OS, Vanilla OS) or wants to do it (PureOS, postmarketOS, elementaryOS). There are lots of different approaches being tried and nobody has the perfect formula for it yet, so it’s an exciting space to watch.

Edit: Clarification from postmarketOS: “We are looking into doing a version of postmarketOS that is image-based/has an immutable file system. But it will still be possible to use postmarketOS without it.”

I personally only half followed some of this while working on other stuff, but it was definitely interesting to hear people discuss the tradeoffs of the various approaches. For example, OSTree doesn’t support offline security which is why Lennart wants A/B/C partitions instead.

OS Stack Bake-Off

After this we had a big OS stack show and tell with people from Debian, GNOME OS, and postmarketOS. From a development/app platform point of view what we need is an OS with:

  • very recent kernel/hardware enablement (because most phones are still in the process of getting mainlined)
  • large, active community around the OS, including a security team
  • image-based, with Flatpak apps
  • up to date middleware (systemd, flatpak, portals, etc.)
  • release cycle in sync with GNOME’s
  • nightly images for testing/dogfooding
  • aligned with GNOME in terms of design philosophy (upstream first, design first, suitably scared of preferences, etc.)

Currently there isn’t an obvious best option, unfortunately. Debian/Mobian has a large community and recent kernels, but its stable version doesn’t have most of the other things we need since its release cycle is way too slow and out of sync with GNOME’s (and using testing/unstable has other problems). postmarketOS is doing lots of great work on hardware enablement and has a lot of what we want, but the lack of systemd makes it impractical (especially once we implement things like homed encryption). GNOME OS nominally has most of what we want, but the community around it is still too small and not enough people are using it full-time.

We’ll see what the future holds in this regard, but I’m hopeful that one or more options will tick all the boxes in the future!

Shell History and Discussion

Another point on the agenda was longer-term planning for the shell. The Phosh/GNOME Shell question has been unaddressed for years, and we keep investing tons of time and energy into maintaining two shells that implement the exact same design.

Unfortunately we didn’t have enough people from the Phosh side at the hackfest to do any actual planning, but we did discuss the history and current state of both projects. People also discussed next steps on the GNOME Shell mobile side, primarily making it clearer that the branch is maintained even though it’s not fully upstream yet, giving it a proper README, having an issue tracker, and so on.

MPRIS Controls

Oliver was interested in MPRIS buttons, so we had a design session about it. The problem here is that different apps need different buttons in their MPRIS widget depending on the use case (e.g. podcast apps need jump buttons, pause doesn’t make much sense for a live stream, etc.). Currently we have no way for apps to tell the system what buttons it needs, so we discussed how this could be done. The results of our session are written up in this issue, and a vague consensus that this could be done as an extension of the existing MPRIS protocol.

To address the short-term issue of not having jump buttons for podcasts, Jonas statically added them to the mobile shell branch for now.

File Opening

Pablo had encountered some oddities with the file opening pattern in his work on Evince, so we took a look at the question more broadly. Turns out we have a lot of different patterns for this, and almost every app behaves slightly differently! We didn’t get as far as defining if/how this could be standardized, but at least we wrote up the status quo and current use cases in apps in an issue.

Flathub

Bart and Kolja from Flathub also joined on Monday and Tuesday, so we worked on the Flathub website a bit (primarily the app tile layout), and discussed a new initiative to make it possible to show the best apps on the home page. The current idea for this is to start off with a new toolbar on Flathub app pages when you’re logged in as a moderator, that allows a mods to set additional metadata on apps. We’d pair this with an outreach campaign to raise the bar on app metadata, and perhaps automated linting for some of the easier to check things.

Bart and Kolja also worked on finally getting the libappstream port done, so that we can have device support metadata, image captions, etc. from Flathub. They made a lot of good progress but this is still not quite done, because there’s lots of edge cases where the new system doesn’t work with some existing app metadata.

Kolja and Bart hacking on Flathub

Mobile Platform Roadmap

A few of us sat down and worked on a priority list of things we’d need in GNOME mobile to be able to realistically daily drive it, including platform, shell, and app features. We documented the results in this issue.

Various other things that happened but that I didn’t follow closely:

  • Pablo and Sonny sat down together and looked over the postmarketOS GNOME session, doing a bit of QA and finding areas where it could be closer to the upstream GNOME vision. Lots of nice improvements since we last looked at it a few months back, and lots more to come :)
  • There was a session about device wakeup APIs. I didn’t attend it, but it sounded like they made progress towards a portal for this so that e.g. alarms can wake up the device when it’s suspended or powered off.
  • Robert, Dorota, Caleb, and others had several in-depth sessions on camera hardware enablement, libcamera and the like
  • Julian got GNOME OS running on the Librem 5 with a recent kernel
GNOME OS running on the Librem 5 for the first time

Overall I found the event very productive and a lot of fun, so thanks everyone for making it a success. In particular, thanks to the GNOME Foundation for sponsoring, Elio Qoshi and Cultivation Space for hosting us, and Sonny for co-organizing. See you next time!

Designing for the Librem 5

So you’re excited about the Librem 5 and GNOME going mobile, and want to start building an app for it. Of course, the first step is to design your app. This can seem quite challenging if you’re just starting out with a new platform, but fear not! In this blog post I’ll walk you through some of the most important UI patterns, and the process of going from idea to mockups step by step. Throughout this I’ll be using a read-it-later app as an example.

The GNOME design philosophy

Before starting to design for a platform, it’s good to familiarize yourself with the design philosophy of the platform. The GNOME Human Interface Guidelines have a “design principles” page which I encourage you to read in its entirety, but will paraphrase a few highlights from here:

Simplicity and Focus — Make sure you have clear goals for your app from the outset, and focus on those. Often it’s better to make a separate application to cover an additional use case rather than cramming too many things into one app (e.g. video podcasts are different enough from audio podcasts to be better off as their own app).

Search and Undo — If there are large amounts of content in your app, provide full-text search to make it easy to find things. Be forgiving about people making mistakes by making it hard to lose data, and never use a warning when you mean undo.

Avoid Preferences — “Just adding an option” often seems like a quick fix, but in most cases you’re just treating symptoms rather than the root cause. It’s better to figure out what that root cause is and fix the problem for everyone, rather than papering over the cracks with a preference. I highly recommend this article by Havoc Pennington on the topic.

Design Process

Now that we’re full of high-minded ideals, let’s jump into the actual design process. Let’s design a great read-it-later app.

We will follow the GNOME design process, which primarily consists of three steps (plus iterations):

  1. Define goals and non-goals for your app
  2. Collect relevant art, i.e. examples of similar apps to borrow ideas from
  3. Make sketches/mockups of the main views and user flows

1. Define Goals

The app we’re designing is going to be a native client for read-it-later web services (such as Pocket). These services allow you to store articles and other web pages that you are interested in, but don’t have time to read right now. That way you can catch up on all the stuff you saved later on, when you have more time. As such, our primary goals are:

  • Listing your saved articles
  • Providing a great, focused experience for reading articles in the app
  • Helping you actually catch up with your reading list
  • Storing articles offline, so they can be read without a network connection

Some non-goals, i.e. things that are out of scope for this application:

  • Social features
  • Content discovery

2. Relevant Art

The next step is to find some examples of existing apps that do similar things. It’s good to look at how other people have solved the same problems, what they do well, and what could be improved before jumping into designing a new app.

So let’s check out the competition:

Pocket on Android (screenshots by me)

Pocket on Android has a lot of features, and a pretty complicated interface. It has lots of categories, social features, a discover section, text-to-speech, and much more. I’ve personally never used most of these features, and they make the app feel quite cluttered. In my experience Pocket is also not very good at helping me get through the list of things I’ve already saved. It feels like it mostly wants me to discover new things to save (and then not read).

Clearly there are some lessons to be learned here for our app.

Instapaper on iOS (screenshots from App Store listing)

I’ve never used the app myself, but judging from screenshots, Instapaper’s UI feels a lot saner and more focused than Pocket. I also really like the rich article previews in the list view and the nice typography.

Wallabag for Android (screenshots from Google Play listing)

Wallabag is a self-hosted alternative to Pocket and Instapaper. This Android client for it (also called Wallabag) is not very sophisticated UI-wise, but it’s a good example of a very simple native client for this kind of service.

Structurally, these apps are all quite similar: a main view with a list of articles, and an article view that just displays the article in a clean, readable format.

Depending on the service, there are multiple lists for different types of articles such as Archive, Highlights, Favorites, Notes, etc. To keep things simple, and because we’re targeting Wallabag first and foremost (since it’s the only self-hosted service), we’re going with only three categories: Unread, Archive, and Favorites.

This means that our application is going to have four main screens we need to design: the three article categories mentioned above plus a reader view, which displays the article content.

3. Sketches/Mockups

Now that we have a basic idea of the structure of the app, we can finally dive into designing the UI. Personally, I like starting off with sketches on paper and then move to Inkscape for more detailed mockups, but you can use any tool you’re familiar with. You don’t need to be good at drawing or a particular application for this, just find a way to visualize your ideas which works for you :)

If you’re using Inkscape for mockups, you might want to check out the GNOME mockup template which contains some common layouts and patterns to use in your designs. If you are looking for GNOME-style symbolic icons for your mockups, you can find them here, here, and here.

When it comes to the layout of an interface, one of the first things to consider is what navigation structure makes the most sense for the type of content you have.

The most common navigation patterns in GNOME apps are the Stack, the View Switcher, and the Sidebar List.

Example of Stack navigation in GNOME Photos

The Stack pattern is when you have completely separate views with no shared UI, and a back button to go back to the overview. This is what Photos does for navigating between the stream of photos and the detailed view of an individual photo, for example. There is a bit more friction to switch between views than with other patterns, but it’s also more focused. This pattern is great for situations where you don’t switch between views a lot.

View switcher in GNOME Clocks

The View Switcher is for cases where there are a small number of views that are equally important or need to always be easily accessible. It’s used in GNOME apps such as Clocks, Music, and Software as the primary navigation. On the desktop, this switcher is always in the headerbar, but there’s work on a new adaptive version of it, which moves to the bottom of the screen for mobile. This is not quite ready yet, but will hit a version of Libhandy near you soon™.

Sidebar List in Fractal

The Sidebar List is for cases where there are a lot of views that you need to switch between often. For example, it’s used in Fractal for the room list, because it gives an overview of all rooms and allows for quick context switching. Of course, on mobile there’s not enough space for a content pane and a sidebar, so there is a Libhandy widget called Leaflet, which transforms from a Sidebar List on desktop to a Stack on mobile.

Experimental branch of GNOME Settings using HdyLeaflet to switch between Sidebar List and Stack navigation

For our read-it-later app, we need navigation to switch between the different lists (Unread, Archive, Favorites), and to switch between list and article views.

The former is a small set of views that we want to be easily accessible, so a view switcher is a good fit. Since we can’t use the shiny new adaptive view switcher widget yet, we can use a plain old view switcher in the header bar for now (though we can already design the UI with the new switcher in mind).

For the latter we could either use a stack or a sidebar list (using the Leaflet widget so it works on mobile). Since we want this app to be a focused reading experience and switching back and forth quickly between articles is not a very common use case, a Stack is probably the best solution here.

This means that our main screens will look something like this:

Quick pencil sketch of the layout for the list and article screens

Article List Screens

Now that we have a basic navigation structure we can design the individual screens in more detail. The three article list screens are basically the same lists with different content.

The main purpose of these screens is to provide a nice, legible list of the saved articles that entices people to catch up with their reading list. In order to do this we’re going with a comfortable layout including article title, preview, and some information about the article.

To help people catch up with their saved articles, we should also try to make the content as interesting as possible. A simple reverse-chronological list of saved items is quite boring, and I’ve noticed in my own use that I often scroll down the list randomly to discover older articles. A potential way to build this into the core experience would be to show the reading list in randomized order, and show the most recently saved articles at the top in a separate category. I’ve tried that in the mockups below.

Mockups of the Unread, Archive and Favorites screens (the latter two are structurally identical, though of course in the real app they’d have different content)

In terms of actions, we need to expose search and selection mode (for operations on multiple elements), as well as the application’s primary menu. The primary menu contains global app-level things such as Help, Preferences, and About.

In selection mode we need the ability to move articles to Favorites and Archive, and delete them from our reading list. Since this is not essential functionality though, we won’t be doing designs for it yet. If you want to learn more, have a look at the selection mode page in the GNOME HIG. The same goes for search (relevant HIG page).

Article Screen

The article screen’s job is pretty straightforward: provide a great reading experience for the saved articles. Since many websites kind of suck in this regard, a reader mode (like Epiphany and Firefox have) should be the default view whenever possible. However, since there’s no guarantee that a given article will be rendered perfectly, we need some way to show to the website with its native styling when necessary.

We also need a way to move an article to Favorites and Archive, delete it, and share it. The most important actions are usually exposed directly in the header bar, but for less important actions (or if there’s not enough space), we can use a secondary menu.

Mockup of the article screen

Desktop

We now know more or less what the app looks like on mobile, but what about the desktop? As with responsive web design, if you design your app for mobile first, it’s usually pretty easy to make it work well on larger screens too.

In this case, since we don’t have any sidebars or other complicated layout elements, the main change happening at larger sizes is that the content column width grows with the window, until it reaches a maximum width comfortable for reading. This can be implemented by wrapping the content area in an HdyColumn. The view switcher also moves up to the header bar, and there is a close button on the right side.

Desktop mockups of some screens

There’s more…

What we now have is the basic structure and most important screens of the application, but that’s of course far from everything. We don’t yet have designs for login and account settings, empty states, first run experience, errors, search, and a number of other things. I wanted to stick to the basics for this post, but perhaps I could expand on these things in future blog posts if there’s interest.

It’s also worth noting that mockups are never final, and interfaces almost always change during implementation, as you learn more about use cases, the underlying technology, and other constraints. Ideally you’d also do some informal user testing on real people, and get feedback on the design that way.

I hope this has been useful as an introduction to designing apps for the Librem 5 (and GNOME more generally). If you have any questions feel free to drop by on #gnome-design on IRC/Matrix or the Librem 5 apps Matrix room (#community-librem-apps:talk.puri.sm).

If you want to play with the mockups I made for this tutorial, here’s the source SVG.

Banquets and Barbecues

tl;dr: We’re splitting up Fractal into two separate apps: One to replace IRC, the other to replace Telegram.

This is an in-depth post on the thinking behind the split of the Fractal app, which was decided at the hackfest in Strasbourg last week. For more information about the hackfest, have a look at my other blog post.

1-1 woes

One of the biggest problems with Fractal at the moment is that 1-1 messaging is pretty terrible. Since the rooms in the sidebar are sorted by most recent activity, high-traffic public rooms (such as GNOME IRC channels) tend to drown out rooms with less traffic, such as 1-1s and small groups. This is problematic because the signal-to-noise ratio in 1-1 chats and small groups tends to be much higher than in high-traffic public rooms. This leaves the user constantly searching for the rooms they care about, while the rooms they don’t care about are always at the top.

1-1 chats are quickly drowned out by high-traffic public rooms in the sidebar

One way to solve this problem is having a favorites group for “important” rooms. This is a feature Fractal has had for a while, and it does solve some of the problems with a room list sorted purely by recent activity. However, it only works well for rooms that are important over long periods of time, and needs to be managed manually. 1-1 chats are often brief, and there can be many of them in parallel. Putting them in favorites doesn’t make sense in many cases, as it would balloon the size of the favorites group, and require lots of manual work when starting or ending a conversation.

The “obvious” solution would be doing what Riot does: Having a separate group of 1-1 rooms in the sidebar, and thereby keeping the 1-1 conversations in one consistent place. However, this creates more problems than it solves. In practice, it results in multiple groups of arbitrary length competing for real estate in the sidebar. If you have a lot of 1-1s, this means that you’ll be able to see very few rooms (even when most of the 1-1s are old and not relevant at the moment). In Riot, this group is capped at 10 visible rooms by default, but that’s still not great if you only need 2 of them at the moment. The category can be collapsed, but then you can’t see which 1-1s have new messages, and it also means lots of busywork collapsing/expanding the group. Clearly this isn’t an ideal solution, which is why we were very hesitant to go down this path.

Riot’s separate 1-1 category doesn’t really solve the problem, because old 1-1s take up a ton of vertical real estate when it’s expanded

A way out?

As we were discussing this issue over the past few months, I started looking more closely at the way people use different messaging tools. One thing I found puzzling is that despite the fact that Matrix theoretically supports the use cases covered by popular apps like Whatsapp and Telegram, few people are actually using it to replace those apps. Instead, they use it to replace IRC and Slack.

Why? My theory is that most chat rooms fall in one of three categories:
Private Chats, which include 1-1s and small groups; Team Chats, which are larger, but still private and invite-only; and Public Rooms, which are basically like IRC.

Team Chats and Public Rooms share many characteristics: Both have relatively high amounts of traffic, and there’s a lot of noise. The main difference is that Team Chats are private and the members rarely change (e.g. a company’s internal Slack), while Public Rooms can be joined by anyone at any time, and there is no expectation of privacy (e.g. #gnome-hackers on IRC).

However, Private Chats have relatively little in common with the other two categories: They are low-traffic, and have little or no noise. This may sound like a small difference, but I think it’s the reason why 1-1s suck in Fractal/Riot/IRC, and why people aren’t using Matrix to replace Telegram.

The Banquet and the Barbecue

I’ve come to the conclusion that one app can’t cover all the use cases that the Matrix protocol supports, and still provide competitive UX. If you design an app to deal with lots of high-traffic rooms (e.g. Riot as it is today), it will suck for 1-1s, so people will use something else for those. Similarly, Telegram is primarily designed for 1-1s and small groups, which is why it’s a terrible experience if you have many high-traffic groups.

If we want Matrix to succeed as more than an IRC/Slack replacement we need multiple apps, each focusing on a distinct use case. For messaging, I think the most important distinction to make is between what I call the Banquet and the Barbecue.

Slack is one of the most widely used apps covering the Banquet use case

The Banquet is a big, loud place. There are tons of people, and you don’t know many of them. Lots of things are happening all the time, and it’s hard to keep track of everything. This is what Matrix is currently mostly used for. Slack, IRC, and Discord are also all in this category.

iMessage is a good example of an app focused on the Barbecue use case

The Barbecue is at the other end of the spectrum: It’s a calm, private environment where friends, family, co-workers, and other acquaintances hang out. Conversations are mostly between 2 or 3 people, slow, and often very personal. Telegram, Whatsapp, iMessage, Facebook Messenger, and a myriad of other chat apps are optimized for this use case.

Fracturing Fractal

Now, what does this mean for Fractal? After a long discussion on Thursday, we decided to split up Fractal into two separate apps with different interfaces, each containing a subset of the user’s Matrix rooms.

Exactly how rooms will be split between the two apps is not 100% clear yet. 1-1s are clearly Barbecue, public rooms are clearly Banquet, but private groups could go either way. For these cases we may need a way to explicitly move rooms between apps. The distinction should probably be part of the Matrix spec, so the intent for a room to be a Barbecue or Banquet room could be set when creating a room, and persist across devices.

The two apps will share practically all the internals, and even large parts of the interface. However, the split will allow us to do some things differently in each app to optimize the interfaces for the different use cases. Some of the changes we’re considering are a bubble-style message view in the Barbecue app, and more room categories (such as low-priority) in the Banquet app’s sidebar.

For more details on the split have a look at the blog posts by Daniel, Eisha, Julian, and Adrien.

Messages and Discussions

How exactly the apps will be branded (and what will happen to the Fractal name we all love) is still being decided, but there is some consensus to move to GNOME-style generic names. The Barbecue app will almost certainly be called “Messages”. For the Banquet app there’s less agreement, but my current favorite is “Discussions”.

Early-stage mockups showing what the two different apps could look like

The Fractal brand will not go away though: We’re thinking of keeping it around as the name of the community project that develops both GNOME Matrix apps, and/or using it for the backend powering both apps.

There are lots of details to be figured out in this transition, both from a design and an implementation perspective, but I’m very excited about this new direction. If you’d like to join the effort, come talk to us on Matrix.

Note: I have no illusions that this change will magically get everyone to leave Whatsapp/Telegram/iMessage and move to Matrix. In the short term, the goal is simply to make Matrix 1-1s a good experience. That said, if we ever want Matrix to make inroads with the general public, I think a move in this direction is an important precondition.

Joining Purism

I’m very happy to announce that I’ve joined Purism. It’s awesome to be working for a company that not only cares about software freedom, but also has Ethical Design as a core principle. My role there is UI/UX designer on the Librem 5, a phone built from the ground up to run free software and GNU/Linux.

As a past user of first Firefox OS and then Ubuntu Touch, I couldn’t be more excited about this. Unlike these previous failed efforts, the Librem 5 is focused on freedom and privacy, because it’s made by people who share that philosophy. It’s using PureOS (a full GNU/Linux distro based on Debian), instead of a completely different technology stack with Android drivers (like Firefox OS and Ubuntu Touch did). To make things even sweeter, the UI will be GTK-based, and we’re using upstream GNOME apps (which we’re adapting with a responsive layout). We’ll also be working on new applications for the phone, such as Calls and Messages, which will work on the desktop as well. We want as much of this work as possible to go upstream, so it can benefit all GNOME users.

It’s still early days, but some of the work around apps should become more concrete in the coming weeks, so expect phone-related discussions in #gnome-design. Let’s make a killer GNOME phone!