Bug 935177 - [Messages][Drafts] Update "discard message" confirmation prompt to options menu/dialog; add "save draft" no-op r=julienw

https://bugzilla.mozilla.org/show_bug.cgi?id=935177

- New strings:
  - save-as-draft      = Save as Draft
  - discard-message = Discard
- Removes window.confirm mechanism
- Implements Multi-option prompt with OptionMenu
- Basic tests to assert the correct operations are performed by the option handlers

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
Bug 936641 - [Messages][Drafts] Create message drafts upon user interaction
Bug 936647 - [Messages][Drafts] Preview drafts threads in thread list r=julienw

https://bugzilla.mozilla.org/show_bug.cgi?id=936647

- index.html:
  - messages-thread-tmpl
    - Adds "icon-draft" class to "icon icon-read" classes
    - Adds data-l10n-id="no-receipient"
    - Adds data-list=draft|thread

- js/desktop-only/mobilemessage.js
  - Updates Draft bootstrapping data

- js/drafts.js
  - Adds read-once and cache to Drafts.request
  - Adds unique id mechanism
  - Updates Drafts.delete to allow deleting all drafts for a threadId
  - Renames Drafts.byId => Drafts.byThreadId
  - Adds Drafts.get(draftId)
  - Updates Drafts.request to abide a local isCached flag.
    - Only load from storage when isCached is false.
  - Updates Drafts.request to revive stored Draft objects as actual Draft objects
  - Adds Draft.List.prototype.latest that points at the latest draft in a Draft.List (ie. for a specified threadId or null key)
  - Adds function guid for creating quasi-unique ids

- js/message_manager.js
  - Adds `draft` property to hold draft object to coordinate with New Message view
  - Calls Drafts.request() from init
  - Calls ThreadListUI.renderDrafts() from onHashChange when hash = #thread-list

- js/thread_list_ui.js
  - Wraps contents in IIFE
  - Adds draftLinks property to map DOM nodes to draftId
  - Updates setContact to include lookup from draft
  - Updates handleEvent to capture draft object on click. Stops looking at 'threads-container'
  - Updates delete to create two lists of deletable items from the selectedInputs array. List is determined by data-list property value.
    - Drafts are deleted similarly to Threads, but will exit immediately if no Threads are to be deleted
    - Drafts.store() is called upon completing delete operation
  - Adds ThreadListUI.renderDrafts to create "Thread List Items" from Draft objects that do not have their own thread
  - Calls ThreadListUI.renderDrafts from ThreadListUI.renderThreads
  - Updates ThreadListUI.createThread to create a "Thread List Item" from a Draft object, or to mark a Thread that has a draft.
  - Updates rendered markup for "Thread List Item"
  - Updates timestamp handling in ThreadListUI.appendThread

- js/thread_ui.js
  - Updates ThreadUI.saveMessageDraft new or replacement drafts

- js/threads.js
  - Expose Thread constructor
  - Adds Thread.prototype.drafts accessor to Drafts.byThreadId(this.id);
  - Adds Thread.prototype.hasDrafts accessor as short hand

- Adds tests to:
  - test/unit/compose_test.js
  - test/unit/drafts_test.js
  - test/unit/media/pixel.jpg
  - test/unit/message_manager_test.js
  - test/unit/mock_async_storage.js
  - test/unit/mock_drafts.js
  - test/unit/mock_navigatormoz_sms.js
  - test/unit/thread_list_ui_test.js
  - test/unit/thread_ui_test.js
  - test/unit/threads_test.js

- Passing both lint and hint

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
Bug 936648 - [Messages][Drafts] Draft display and interaction within a thread r=rwaldron
Bug 946995 - [Messages][Drafts] MMS Drafts don't restore correctly after app closes/restarts r=rwaldron

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
Bug 946989 - [Messages][Drafts] Duplicate threadless drafts get saved r=rwaldron

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
Bug 947215 - [Messages][Drafts] Do not try to match an existing thread when saving a threadless draft r=rwaldron

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
jshint nits

Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
Bug 949137 - [Messages][Drafts] Composer doesn't clear after sending a new draft