Kube in Randa

I’ve spent the last few days with fellow KDE hackers in beautiful Randa in the Swiss Mountains.
It’s an annual event that focuses on a specific topic every year, and this time accessibility was up, so Michael and me made our way up here to improve Kube in that direction (and to enjoy the scenic surroundings of course).

I have to admit we didn’t spend all our time on accessibilty, since we’ve recently done a big push in that direction already with keyboard navigation and translation preparations. Anyhow, here’s an overview on what we’ve worked on:

Query performance

While it might now be a showstopper, there is an annoyance in Kube that if you initially sync a lot of mail (my INBOX alone contains 40k) this not only uses a lot of CPU in the synchronizer process (which is expected), but also in the Kube client process, which seems odd at first.

The reason for this are the live queries, which update themselves whenever the resource signals that it has a new revision available (A new revision could be a new mail or a modification for instance). Usually, when we process an update we do so incrementally. If you just received a new mail or two, or something has been marked as read etc., that is also the sensible thing to do. It’s a comparatively tiny amount of work, and we really want incremental changes in the result anyways, otherwise we’d mess up the client’s UI state (selection, scroll position, …).

However, when we fetch 40k mails that also means we get 40k updates that we have to process and it’s surprisingly hard to avoid that:

  • We don’t know in advance that there will be 40k updates, so we have to process the updates initially.
  • We can’t really skip any updates, because any update might affect what we have in the view. We just don’t know until we’ve already processed it.
  • We can’t just fall back to redoing the full query because we need incremental changes, otherwise you’d see a blinking UI until the sync is done.
  • We don’t want to just stop updating until the sync is done, because in most cases you already have useful data to work with, so this is really a background task, and we don’t want to block all updates.

If you end up processing the larger part of the data-set as incremental update it becomes naturally really expensive, because you can’t leverage the indexes which made queries efficient in the first place. So this is not something that can just be optimized away.

This means some middleground has to be struck which allows for updates, but doesn’t render the application maxed out because it’s updating so fast.

A possible approach to fix this would be the following:

  • Set some threshold when it becomes cheaper to redo the query instead of processing the updates.
  • If the threshold is reached, redo the query from scratch.
  • Diff the current results with the redone results so we can still update the UI incrementally.
  • Apply some event compression to the revision updates, so we land in the optimized path quicker.

Given that this really isn’t a huge problem right now, since the application does remain responsive (querying is done in a separate thread), and this will only ever happen if you sync a large folder for the first time, I won’t spend a lot of time on that for now. The most important part was figuring out why this problem appeared in the first place, and understanding it’s reasons and implications. This will allow us to attack it properly once we get to it.

HTML composer

Kube’s composer is currently a simple text field where you can type plain text. This is obviously not the end goal.
To explore our options in providing a more advanced composer, we tried prototyping a simple HTML editor.
Unfortunately our experiments showed that QML isn’t really up to that yet. The official example falls flat on it’s face when trying it (it simply fails except for a few specific cases), and the “API” to do any sort of formatting is more a hack than anything else.

Granted, the API docs of the TextArea also state that you can’t modify the internal document, or in other words, no HTML composer for us.

The options we have left are:

  • Some custom text editing component (sounds like a lot of work, probably is).
  • Try to hack around TextAreas deficiencies until we find some magic combination that works.
  • Use a WebView and implement everything in javascript (now that’s just sad).

For now the item is postponed.

GPG Support

We’ve scoped out what we want to reach for initial GPG support in Kube. While we already have read-only GPG support (we can decrypt mails and verify signatures), there is some more work to be done until we can also sign and encrypt messages we’re sending. The focus will be on keeping things simple to get the job done, and not build the most advanced GPG interface ever.

Things that will happen are:

  • Key selection for the account that will then be used for encryption.
  • Key setup for new accounts that don’t have a key yet (either by importing an existing key or creating a new one)
  • Encryption option in the composer that depends on the availability of keys for all recipients.
  • Key selection for users in the addressbook.

All of it can be found on Phabricator

Cross platform builds

Since we had some cross platform building experts on site, I explored some of our options:

  • Cross compiling for Windows with MXE.
  • Building on Windows and OSX using craft.
  • Building with some custom scripts on Windows.
  • Building with macports on OSX.
  • Building with brew on OSX.

Although I had mixed feelings about craft back from the days when I used emerge (the craft predecessor) to build Kontact on Windows,
it at least looks like the most sensible option still.

Crosscompiling using MXE seems ok-ish for Windows; I had some success for parts of the stack and the rest will just be the grunt work of making tarballs and writing build definition files. At least that way you don’t have to work on a Windows system. However I heard that the compiled end-result will just not be as good as using native compilers, so perhaps it’s not worth it to trade some building convenience for a sub-par end result.
Also, writing the definition files is pretty exactly the same as for craft, and MXE would be for Windows only.

So, looks like I’ll be doing another round with craft sometime soonish.

Plasma phone

IMG_20170914_141340

It kinda works.

Bushan Sha quickly wipped up a package for the Plasma Phone and installed it, which allowed us to see Kube running for the first time on a mobile device, which felt surprisingly cool 😉

There clearly are some rough edges, such as the UI being completely unsuitable for that form factor (who would have thought…), and a bug in one of the QML components which breaks folder selection using a touch screen. Still, it was nice to see =)

Input validation

To improve the UX with forms in Kube, or more specifically the configuration dialog, we wanted to provide some feedback to the user on what fields need to be filled out. Michael implemented a neat little visualization that that marks invalid input fields and gently fades away once the input becomes valid.

Screenshot_20170919_232321

Screenshot_20170919_232514

So far we only validate that fields are not empty, but that can be changed by assigning new validators that e.g. check that an email address field indeed contains a valid email address.

Recap

It was once again a very productive week, with lot’s of good food and a couple of fun hikes in between to clear out the head.
Besides the usual work going on it’s invaluable to have an exchange with other people that just might have solved the problem already that you’re going to spend the next few weeks on. So in many ways this is not only about a concentrated work effort, but also about professional training and exchange, and that is only possible in when you’re sitting together with those people.

I’d like to thank the whole team that organized the sprint, took care of us with great food and lot’s of chocolate and generally just made our stay in Randa great once more.

If you made it all the way down here and skipped the fundraiser on top, please consider donating something, it’s the only way we can keep doing meetings like this and they are invaluable for us as a community.

Advertisements

Last week in Kube

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

  • We now synchronize both contacts and drafts when opening the composer. The former are required for autocompletion, the latter to show your drafts.
  • A maillist filter bar to replace the currently defunct search.
  • We now synchronize the currently selected folder every 5min.
  • Bumped Qt requirement to 5.9 so we can finally use the focus stealing prevention of the webengineview.
  • Automatically launch into the account configuration if no accounts are set-up.
  • A single account mode for deployments that support only a single account. This can currently only be activated with a switch in the qml code.
  • Prototyped a simple html editor, unfortunately the QML TextArea API is just not there yet and the end result ended up buggy. Postponed for now.
  • Worked out a plan for gpg based encryption that is now available as phabricator tickets for the next milestone.
  • Improved input form validation and feedback.
  • Did some work towards improving a performance bottleneck in live queries when a lot (thousands) of updates are coming in (such as during the initial sync). Not quite there yet though.
  • Did some cross compilation experiments with MXE for Windows and without MXE for Android. WIP
  • Witnessed Kube on the Plasma Phone. This will require an adapted UI but generally seems to actually work.
  • Fixed some layouting issues where some TextAreas wouldn’t resize with the rest of the UI.

Kube Commits, Sink Commits

Previous updates

Last week in Kube

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

  • Fixed scrolling behaviour with a mouse wheel (it used to be very slow).
  • Prepared the 0.4 release.
  • Fixed RE: prefixing for replies.
  • Fixed issue where searching for removed entities would result in a query going through all uids instead of only the ones of a specific type. As this touched storage a “sinksh upgrade” will be required to clean up.
  • Added some missing icons that where symlink targets.
  • Inverted colors on folderview scrollbar to match that area of the UI.
  • Fixed layouting issues with long attachment lists in the composer.

Kube Commits, Sink Commits

Previous updates

Last week in Kube

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

  • Improved connected status tracking in IMAP resource. The IMAP resource now correctly goes into offline status if an operation times out.
  • Introduced a ConnectionLost error when a connection times out that Kube can display.
  • Fixed a couple of threading issues in sink. One could lead to a deadlock on shutdown of the synchronizer process which resulted in synchronizer processes not dying.
  • Fixed account status monitoring when creating a new account. Previously the account status would not include newly created resources, which broke account status monitoring when creating a new account without restarting the application afterwards.
  • The scrollbars are now properly hidden if the content is smaller than the container (nothing to scroll).
  • Set a color according to the signature state on the colorbar indicating the signature state.
  • Added a tooltip to the signature state bar providing some basic info. This is a stub until we have a proper UI element for that.

Kube Commits, Sink Commits

Previous updates

Last week in Kube

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

  • WebEngineProfile no longer blocks kube on exit. It looks like some webengine code ends up in a deadlock when installing a QWebEngineUrlRequestInterceptoron the default profile from the main thread. It was solved by creating a custom WebEngineProfile as custom QML element.
  • Fixed scrolling issue where a slow loading mail would result in the positioning code interfering with user scrolling. This fixes email positioning in the conversation view.
  • Made scrollbars always visible. This is to help people that use the mouse to grab the scrollbar handle for scrolling.
  • Fixed some account config corner cases and improved user feedback when saving changes.
  • Large CMake cleanup to remove duplication and to clarify what settings we set.
  • Made sure all tests pass again, cleaned up testsuite.
  • Fixed encoding issue when replying to mail that would mangle some utf-8 chars.
  • Fixed font sizes so the same size is applied throughout the application. This resolves some scaling issues we had on some devices.
  • Changed connected/disconnected detection so resources that have no known status yet turn up as disconnected.

Continue reading “Last week in Kube”

Progress on Kube

A lot has happened since the last release, so let me bring you up to speed on what is cooking for the 0.4 release.
We’ve been mostly focusing on ironing out UX problems all over the place. It turns out, when writing desktop applications using QtQuick you’ll be ending up with a lot of details to figure out for yourself.

Kube Components

We noticed that we end up modifying most components (buttons, listviews, treeviews, ….), so we ended up “subclassing” (as far as that exists in QML), most components. In some cases this is just to consistently set some default options which we would otherwise have to duplicate, in some cases it’s about styling where we have to replace default styling either for pure visual reasons (to make it pretty), or for additional functionality (proper focus indicators).
In some cases it’s even behavioral as in the scrolling case you’ll see later on.

In any case, it’s very well worth it to create your own components as soon as you realize you can’t live with the defaults (or rely on the defaults of a framework like Kirigami), because you’ll have a much easier time at maintaining consistency, improving existing components and generally just end up with much cleaner code.

Scrolling

One of the first issues to tackle was the scrolling behavior. Scrolling is mostly implemented in Flickable, though i.e. QtQuick.Controls.ScrollView overrides it’s behavior to provide a more desktopy scroll feeling. The problem is indeed that Flickables flicking behavior is absolutely unusable on a desktop system. It depends a lot on your input devices, with some high-precision trackpads it apparently ends up doing alright, but in general it’s just designed for touch interaction.

Problems include:

  • Way to fast scrolling speed.
  • The flicking is way to long and only stoppable by scrolling in the opposite direction (at least with my trackpad and mouse).
  • Difficulties in fine positioning e.g. a listview, scrolling is generally already too fast and sometimes the view just dashes off.

These problems are unfortunately not solvable by somehow configuring the Flickable (Believe me, I’ve tried), so what we ended up doing is
overriding its behavior. This is done using a MouseArea that we overlay with the flickable (ScrollHelper.qml) and then manually control the scrolling position.

This is a very similar approach to what also QtQuick.Controls.ScrollView does and what Kirigami does as well for some of its components.

It’s not perfect and apparently doesn’t yet play nicely with some mice as the fine tuning is difficult with various input devices. There is a variety of high/low precision devices, some of which give pixel deltas (so absolute positioning), and some of them give angle deltas (which are some sort of ticks), and some of them of course give both and don’t tell you which to use. What seems to work best is trying to calculate both into absolute pixel deltas and then just use either of the values (preferably the pixel delta one it seems). This will give you about the behavior you get in e.g. a browser, so that works IMO nicely.

For most components this was fortunately easy to add since we already had custom components for them, so we could just add the ScrollHelper there.
For others like the TreeView it was a bit more involved. The reason is that the TreeView itself is already a ScrollView, which not only implements a different scrolling behavior, but also brings its own scrollbars which look different from what we’re using everywhere else. The solution ended up being to wrap it with another Flickable so we can use our usual approach. Not pretty, but the fewer components we have that implement the same thing yet again in a different way the better.

Focus visualization

As I started to look into keyboard navigation the first thing I noticed was that the focus visualization was severely lacking. If you move around in the UI by keyboard only you always need to be able to follow the currently focused item, but many of our components didn’t differentiate between having keyboard focus or being selected and sometimes lacked a focus visualization altogether. The result was that the focus would randomly vanish as you for instance focused an already selected element in a listview, or you couldn’t differentiate if you have now moved the focus to another list-item or already selected it.

The result of it all is a highlighting scheme that we have now applied fairly consistently:

  • We have a highlight for selected items
  • We have a lighter highlight for focus
  • …and we draw a border around items that have focus but are somehow not suitable for the light highlight. This is typically either because it’s i.e. text content (where a highlight would be distracting), or because it’s an item that is already selected (highlight over highlight doesn’t really work).

Once again we were only able to implement this because we had the necessary components in place.

Keyboard navigation

Next up came keyboard navigation. I already took a couple of stabs at this, so I was determined to solve this for good this time. Alas, it wasn’t exactly trivial. The most important thing to remember is that you will need a lot of FocusScopes. FocusScopes are used to componentize the UI into focusable areas that can then have focusable subareas and so on. This allows your custom built component that typically consists of a couple of items to deal with focus in it’s own little domain, without worrying about the rest of the application. It’s quite a bit of manual work with a lot of experimenting, so it’s best done early in the development process.

The rest is then about juggling the focus and focusOnTab properties to direct the focus to the correct places.

Of course arrow-key navigation still needs to be implemented separately, which is done for all list- and treeviews.

The result of this is that it’s now possible to completely (I think?) navigate kube by keyboard.

There are some rough edges like the webview stealing the focus every time it loads something (something we can only fix with Qt 5.9, which is taking it’s sweet time to become available on my distro), and there is work to be done on shortcuts, but the basics are in place now.

Translations

While at it working on accessibility stuff we figured it’s about time we prepare translations as well. We’ll be using Qt based translations because it seems to be good enough and the QML integration of ki18n comes with some unwelcome dependencies. Nothing unsolvable of course but the mantra is definitely not to have dependencies that we don’t know what for.

Anyways, Michael went through the codebase and converted all strings to translatable, and we have a Messages.sh script, so that should be pretty much good to go now. I don’t think we’ll have translations for 0.4 already, but it’s good to have the infrastructure in place.

Copyable labels

Another interesting little challenge was when we noticed that it’s sometimes convenient to copy some text you see on your screen. It’s actually pretty annoying if you have to manually type off the address you just looked up in the address book. However, if you’re just using QtQuick.Controls2.Label, that’s exactly what you’re going to have to do.

Cursor based selection, as we’re used to from most desktop applications, has a couple of challenges.

  • If you have to implement that cursor/selection stuff yourself it’s actually rather complicated.
  • The text you want to copy is more often than not distributed over a couple of labels that are somehow positioned relative to each other, which makes implementing cursor based selection even more complicated.
  • Because you’re copying visually randomly distributed labels and end up with a single blob of text it’s not trivial to turn that into usable plaintext. We all know the moment you paste something from a website into a text document and it just ends up being an unrecognizable mess.
  • Cursor based selection is not going to be great with touch interaction (which we’ll want eventually).

Screenshot_20170819_232959

The solution we settled for instead is that of selectable items. In essence a selectable item is a manual grouping of a couple of labels that can be copied as once using a shortcut or a context menu action. This allows the programmer to prepare useful chunks of copyable information (say an address in an addressbook), and allows him to make sure it also ends up in a sane formatting, no matter how it’s displayed in the view itself.

The downside of this is of course that you can no longer just copy random bits of a text you see, it’s all or nothing. But since you’re going to paste it into a text editor anyways that shouldn’t be a big deal. The benefit of it, and I think this is a genuine improvement, is that you can just quickly copy something and you always get the same result, and you don’t have to deal with finicky cursor positions that just missed that one letter again.

Flatpak

The flatpak now actually works! Still not perfect (you need to use –devel), but try for yourself: Instructions
Thanks to Aleix Pol we should have nightly builds available as well =)

Other changes include:

  • The threading index now merges subthreads once all messages become available. This is necessary to correctly build the threading index if messages are not delivered in order (so there is a missing link between messages). Because we build a persistent threading index when receiving the messages (so we can avoid doing that in memory on every load), we have to detect that case and merge the two subthreads that exist before the missing link becomes available.
  • The conversation view was ported away from QtQuick’s ListView. The ListView was only usable with non-uniformly sized items through a couple of hacks and never played well with positioning at the last mail in the conversation. We’re now using a custom solution based on a Flickable + Column + Repeater, which works much better. This means we’re always rendering all mails in a thread, but we had to do that before anyways (otherwise scrolling became impossible), and we could also improve it with the new solution by only rendering currently visible mails (at the cost of loosing an accurate scrollbar).
  • The email parsing was moved into it’s own threads. Gpgme is dead slow, so (email-)threads containing signatures would visibly stutter (Without signature the parsing is ~1ms, with ~150ms. With encryption we can easily go up to ~1s). With the new code this no longer blocks the view and multiple mails are parsed in parallel, which makes it nice and snappy.
  • Lot’s of cleanup and porting to QtQuick.Controls2.
  • Lot’s of fixes big and small.

It’s been a busy couple of weeks.

Randa

The annual Randa meeting is coming up and it needs your support! Randa will give us another week of concentrated effort to work on Kube’s keyboard navigation, translation and other interaction issues we still have. Those sprints are very valuable for us, and are in dire need of support to finance the whole endavour, so any help would be more than welcome: https://www.kde.org/fundraisers/randameetings2017/

Thanks!

Release of Kube 0.3.1

“Kube is a modern communication and collaboration client built with QtQuick on top of a high performance, low resource usage core. It provides online and offline access to all your mail, contacts, calendars, notes, todo’s and more. With a strong focus on usability, the team works with designers and UX experts from the ground up, to build a product that is not only visually appealing but also a joy to use.”

For more info, head over to: kube.kde.org

Kube 0.3.1 is out the door.

Over the past months we’ve been working hard on turning Kube into something more useful than a pure techpreview, and while Kube 0.3.1 still isn’t anywhere near production ready, I can finally say that I can use it for most of my email needs.

First, let’s get out of the way what doesn’t work just yet so you know what you can expect.

  • We don’t provide any upgrade path, so with every release it is necessary to run “sinksh upgrade” manually, which currently simply nukes all your local caches (but not the config, so you’ll just have to resync).
  • Email sending is limited to plaintext (we convert html mails to plaintext on reply).
  • Passwords are stored in plaintext in configuration files, which may not be acceptable to you.
  • It’s of course also possible that you will experience unpleasant surprises if you use it for any relevant emailing.
  • The scrolling experience depends a lot on your input devices. This seems to be a Qt internal defect that we hope will resolve itself with Qt 5.9.

What we do have though is:

  • A working composer that is right now very basic but has a lot of potential (more about that in a separate blogpost).
  • Support for reading encrypted and and signed mails (although the UI support is still very basic for details on validitiy etc).
  • A basic CardDAV based Addressbook.
  • A fairly pleasant reading experience (IMO anyways).

Lot’s of work also went into the application architecture, UI feedback for user interactions (e.g. progress during synchronization), cleanup of our dependency tree and the concept of how we will continue to evolve Kube.

The UI team did excellent work on the UI front (surprise!) and has cleaned up the look considerably. Due to the realization that our look depends a lot on the looks of the icon theme, we are now shipping an icon theme with Kube (based on breeze). This will also further our goal to work equally well on a variety of platforms where we cannot assume a specific icon theme to be available.

We have also transitioned mostly to QtQuickControls2, the remaining bits will require Qt 5.9. We’ll then plan on staying on this LTS release for the time being.

Overall, while not quite ready for prime time, this release marks a very important milestone on our road to a production ready release and I’m very happy to have a lot of issues, that have been bothering us for long, finally resolved.
I also think that while we’ll still have to do one or the other large change every now and then, the codebase can now start to settle as we have resolved our largest problems.

If you’d like to read more or give it a shot, please head over to kube.kde.org for installation instructions for experimental builds for Fedora 25 and Archlinux.

Tarballs

https://download.kde.org/unstable/sink/0.3.0/src/sink-0.3.0.tar.xz.mirrorlist
https://download.kde.org/unstable/kube/0.3.1/src/kube-0.3.1.tar.xz.mirrorlist

Randa

Unfortunately I can’t attend Akademy this year, but if you’d like to work on Kube, talk to us, have a Beer or just go for a hike, make sure to come to Randa for the annual Randa Meetings from the 10.09.2017 – 16.09.2017. To register click here.