Thunderbird2:Tags
Tracked by: bug 114656
Contents
Design Overview
Objectives
The primary objectives of this project are to:
- Allow the user an arbitrary number of tags per message.
- Create interesting views/saved searches based on tags
Background
Thunderbird 1.5 allowed the user to apply one of five labels to a message. We'd like to make that much more general and useful, and replace the label feature with the tags feature.
Front End Design
You should be able to do the following:
- Using a context menu, add an existing or new tag to a message.
- Remove a tag from a message
- Delete a tag from the application (effectively removing it from all messages)
- Optionally associate a color with a tag
- Rename a tag
- Search on messages with a tag
- Create saved searches based on tags
Implementation Issues
These are basically me thinking aloud so please pardon the rambling.
How should we store user-defined tags on an imap server? How should we store them in the db?
There are a bunch of issues here:
IMAP keywords allow basically alphanumeric keywords; no spaces, no special characters. We can use imap mod-utf7 to handle unicode chars, but some special chars can't be represented.
I think we're going to have to do something like Pine does of storing what keywords to display as tags, and what tag to display. Under normal circumstances, the user should never have to edit this file. We'll pre-populate it with the custom keywords we use (Junk/NonJunk/$label1-6) and mark them as keywords to ignore. When the user adds a tag, we'll add an entry to the file, along with the tag to display for the keyword. The keyword will be created by stripping out the illegal chars in the tag, and converting to imap mod utf7 (probably in the other order). When the user "renames" a tag, we'll just redo the mapping, and replace the tag in all the messages. When the user deletes a tag, we'll just mark the keyword as one to ignore, and remove the tag from all the messages that have that tag. This mapping file should be cross account, probably, so that if you add a tag, it applies to all accounts.
I had planned to have a separate mapping file, something like taginfo.dat, that users could transfer between profiles. Scott suggests using preferences to store the tag info. That would save me some implementation time, but make it more difficult for users to share taginfo across profiles and machines. I plan on hiding this behind an nsIMsgTagInfo service so we can choose a persistence mechanism later, and if people want to plug in other mechanisms, they can.
As far as losing tags when the .msf files are deleted is concerned, my plan is to add UI for rebuilding a summary file, and have the implementation be non-destructive as far as keywords is concerned. It would basically reparse the folder, and rethread the messages, but maintain the keywords. This should make it less likely that people will delete the .msf file directly.
Iterating over all the db's and messages to rename or remove a tag would be ugly. So we'll use the mapping file for that as well, and just stop displaying those tags. That means we'll store the keywords in the dbs, and do the conversion at display time, even for local folders, etc.
How are we going to store the keywords in the db? One property, or multiple properties? If one property, comma-separated, with ',' escaped? It turns out that we're already storing imap keywords in a single property on the header, space delimited. Unless there's some compelling reason to change that, I think we'll go with that approach.
Tasks
Local mail-specific:
- When downloading pop3 mail, leave an x-mozilla-keys header with space for writing tags.
- When parsing a mailbox, parse the x-mozilla-keys header(s)
- When setting tags on a local message, write to x-mozilla-keys header if room
- When compacting a folder, if we have more tags in the db for the msg than we have space in the mailbox, add an other x-mozilla-key header
- Make sure x-mozilla-keys are stripped the same way x-account-key is stripped
Tag <-> Keyword mapping service
- Define interface
- Implement persistence
- Implement methods
- Upgrade from labels
Design methods for getting and setting tags
Implementation
Tags are stored in preferences of the form
"mailnews.tags.<key>.tag", "unicode string"
"mailnews.tags.<key>.color, "color string"
The key is an imap mod-utf7 version of the tag, suitable for use in a pref name, an imap keyword, and part of an x-mozilla-keys header. So, as you might guess, we actually store the key persistently, and translate it to the tag for display purposes. This also allows us to rename a tag by changing the pref without changing all the messages that have that tag. We can also remove a tag by removing the pref, and the key stored in the messages will then be ignored.