My pull request has been merged and is included in the latest builds on OBS. Try it out and report issues! 🙂
Thanks to my mentors, GNOME and Google for this great GSoC experience!
Last days of GSoC
I added an option to get back to the end of a conversation. A button offering this functionality appears as soon as the conversation isn’t scrolled all the way down anymore. This is handy after one clicked on a search result and ended up far up the conversation.
Furthermore, I finished auto completion for search filters. This allows for way easier usage of filter terms, as you don’t have to write full addresses anymore. The auto-completion also searches in names, so in case you don’t know the corresponding address by heart, it still is easy to use.
For each search hit in the results, three messages are (partially) displayed: The actual hit and the messages before and after that. The hit is clickable and clicking it will jump to the hit in the conversation history. The clicked message is highlighted with a CSS animation by fading a background color in and out.
I added placeholders to clarify the states where no results are shown because nothing was searched yet and where no results are shown because there where no matching results. Following the GNOME HIG, the placeholders contain an icon, a state description and suggestions on how to proceed.
Minor change of plans
In my UI mockups I planed to collapse the search sidebar into only displaying the search entry after a hit was clicked. This was supposed to let the user know that a search is still active and that he/she can resume the search without requiring much screen space.
However, this introduced more states to the search feature and thus leaves more room for confusion. Also, reopening the search from the collapsed state would need a click/shortcut, while just completely reopening the search would require the same amount of interaction. Thus, the collapsed state does not save the user interaction steps and might be harder to understand.
Instead, the search text is simply not removed from the search entry when clicking on a result. When the user desires to resume the search to explore other results, he/she can open the search again and will find the old search results. The text is marked, thus simply typing over it is possible. The search text is still reset when changing conversations.
I had to hunt down and fix some displaying issues in the history search and other bugs I introduced while refactoring parts of the conversation view structure.
During the final days
I have been working on user name auto-completion and nice displaying of filters. There is some final work and testing to be done on them and then I can open a PR!
One of the cool features of modern search engines – both in web search and chat search – is the ability to further filter the results using special expressions. Inspired by the same functionality in Slack, I prototyped a first set of three filters:
from: Only show messages sent by a specific user – in a channel or private chat
in: Only show messages send to a specific channel, by any user of that channel
with: Only show messages that appeared in a private chat
More to be added
Obviously there is a lot of potential for more filters to be added:
before: Given a date, show messages sent before that date
after: Given a date, show messages sent after that date
on: Given a date, show messages sent on that date.
Dates may either be given by day (optional for before and after, defaulting to first or last day of month, respectively), month and year (optional, defaulting to the last occurrence of that date) or using a relative statement like today or yesterday
during: Given a time-span, show messages sent during this time-span (inclusive)
There are different ways to specify a time-span: using two dates (as defined above), a month or year description or again using relative statements like last week.
has: Check if the message contains something in the body to fulfill a criteria. Candidates here are link and mention, but as time passes, there might be other things to do here.
Auto-completion and user interface improvements
These cool filters would be really useless, if they are hard to use. Nobody wants to type the full ID of another user, especially for whispered messages in channel, they can become annoying long and complex. Best way to solve this is to provide a user friendly auto-completion, not only in its verbatim meaning: being able to use a contact’s name instead of the ID drastically eases the use of this feature. I also imagine the auto-completion hints to show the contact’s picture, to make things even more convenient.
But even after we had the auto-completion done, it would be great to have the filter visible in a more user-friendly way. There is no reason that I can type in the middle of a filter statement – it will usually just make it invalid. Displaying the filter more like a tag (that can only be removed as whole) makes way more sense – and also allows for more flexible ways to display those – again imagine to somehow show the contact’s picture next to that tag.
We – me and my mentors – are still not sure how exactly we’d like all these filters and user interface to be, just that it is definitely needed. I’ll explore different ways to do all this, but this might not be completed before the end of the Google Summer of Code (August 6) – especially as I am still working on fixing some bugs and cleaning up the code. Let’s see how far we get within this time.
As announced in my previous blog post, we’ll use SQLite’s Full-Text-Search (FTS) functionality for fast and powerful search functionality directly in the database. To make use of FTS, I had to extend the Dino’s qlite library, which provides a database abstraction for SQLite. The new functionality is now added with qlite’s design in mind (descriptive language for database, tables and columns, SQL-alike query functions with some type-checking at compile time), allowing to enable full-featured FTS for a specified set of columns with just a single statement.
With this new FTS functionality it was an easy thing to add a search processing unit to libdino so we can easily perform message searches from the UI. This is also the place where I’ll add support for filter statement pre-processing (see Next steps).
Jump to message
The search UI should include a way to jump to a specific message from the results in order to read previous and following messages. After jumping to a message, the user should be able to infinitely scroll downwards while the application should continuously load and display following messages. This functionality was already implemented for scrolling upwards.
I implemented jumping to a message in history by fetching and displaying the respective message and some previous and following messages. I also implemented infinite downwards scrolling.
While looking into implementing this, I noticed that all items shown in the conversation view are organized around messages. However, file transfers should be treated the same as messages in many cases. This rarely caused issues when scrolling up to load history and in conversations containing only non-message content. I refactored the code around conversation content and introduced an abstraction layer for content items. The refactoring helped me to implement message fetching in a nicer way.
Search User Interface
At the top of my post is a screenshot how the user interface currently looks like. Doing a mock-up first helped a lot. There are still some displaying issues. After those are solved, I will upload a short video of the message search in use.
The user interface still needs polishing. Furthermore, I will implement an auto-completion for the search bar, which will complete user names. If a user name is specified, only messages exchanged with that user will be displayed in the results.
The first two weeks of GSoC are over now – time to share some insights on what I have been doing so far to provide a great search user experience in Dino by the end of the summer.
User interface design
To get an idea of what is needed to properly fulfill my summer project, it’s not a bad thing to start with a design mockup: It brings everyone on the same page of how the search feature should look in the end and also emphasizes the requirements on the backend code.
This design aligns with a proposal to add a sidebar to Dino when used in a large window. The sidebar is supposed to provide extended information on a chat, like group chat members or vCard data. While the sidebar idea is still not fully developed, this search design can easily replace such a sidebar (instead of overlaying the content like in the small window scenario displayed above) – very similar to the behavior of tools like Slack, that do feature a sidebar as well.
SQLite’s FTS (full-text search) functionality
In my introductory blog post, I already teased that I will look into SQLite’s FTS feature as a possibility to implement a fast and powerful search functionality for Dino. Now after looking into the functionality, I wonder why I never heard of this feature before. While I had a basic system in mind to do full-text search using a keyword index, the FTS functionality is far more advanced while allowing way easier usage and comes with a lot of awesome functionality like automated preview snippet generation. While this is most likely not interesting for Dino (because instant messages are usually not that long that it would make sense to not pull the full message from the database engine), others like the complex query expressions for the MATCH operator might be handy – although my initial test implementation does not make use of them.
My initial time plan for the GSoC asked for the first two weeks to be used to implement a full-test search functionality. After I found out that SQLite’s FTS already provides all the features we need, I directly stepped forward to the user interface designing phase initially intended for weeks 3 and 4. I will continue with implementing the user interface and finalize the FTS based search implementation in the upcoming weeks.
On May 14th the Google Summer of Code 2018 coding period will start and with it my project on Dino. I want to contribute making Dino a fresh and sufficiently full-featured XMPP client by implementing message search during the next months. I am excited to having been accepted and to learn a lot during the project.
To the end of creating a intuitive and fast message search I will create a data structure capable of efficient keyword search, design an (awesome) UI and implement it. For the efficient data structure I will first have a look at sqlite’s FTS. For the UI I’ll start with some mockups. I will report my progress in this blog.