Mailspring/internal_packages/thread-list/lib/draft-list-store.coffee
Evan Morikawa 6c881f4f64 fix(draft-list): draft list removes draft when the message sends
Summary:
This started when I noticed that drafts weren't dissapearing from the
draft list after send. This was a pretty big bug because if you ever
clicked on one again and tried to re-send it would throw a 400 error
saying the draft id doesn't exist.

This uncovered a few fundamental issues with the DB.

First of all, the reason the draft list wasn't updating was because the DB
trigger that happened when we got in a new message, was being ignored
since the diff contained no drafts (it's now a message).

The bigger issue was that if you had a draft with only a clientId, gave it
a serverId, and tried to call "save", the REPLACE INTO method would not
update the old object, but rather create a second duplicate. This is
because the `id` field was being used as the PRIMARY KEY, and in this
case, that `id` field changed! The fix was to change the PRIMARY KEY to be
the `cilent_id` instead of the `id` and use that as the REPLACE INTO
index.

We still need the `id` field; however, because all of our reads depend on
that field usually being the serverId

Fixes T3507

Test Plan: See new and updated tests

Reviewers: dillon, bengotow

Reviewed By: bengotow

Maniphest Tasks: T3507

Differential Revision: https://phab.nylas.com/D1992
2015-09-08 13:11:34 -07:00

62 lines
1.6 KiB
CoffeeScript

Reflux = require 'reflux'
_ = require 'underscore'
{Message,
Actions,
DatabaseStore,
AccountStore,
FocusedContentStore,
DestroyDraftTask,
DatabaseView} = require 'nylas-exports'
module.exports =
DraftListStore = Reflux.createStore
init: ->
@listenTo DatabaseStore, @_onDataChanged
@listenTo AccountStore, @_onAccountChanged
@listenTo Actions.deleteSelection, @_onDeleteSelection
# It's important to listen to sendDraftSuccess because the
# _onDataChanged method will ignore our newly created draft because it
# has its draft bit set to false (since it's now a message)!
@listenTo Actions.sendDraftSuccess, => @_view.invalidate()
@_createView()
view: ->
@_view
_createView: ->
account = AccountStore.current()
if @unlisten
@unlisten()
@_view = null
return unless account
@_view = new DatabaseView Message,
matchers: [
Message.attributes.accountId.equal(account.id)
Message.attributes.draft.equal(true)
],
includes: [Message.attributes.body]
orders: [Message.attributes.date.descending()]
@unlisten = @_view.listen => @trigger({})
_onAccountChanged: ->
@_createView()
_onDataChanged: (change) ->
return unless change.objectClass is Message.name
containsDraft = _.some(change.objects, (msg) -> msg.draft)
return unless containsDraft
@_view.invalidate()
_onDeleteSelection: ->
selected = @_view.selection.items()
for item in selected
Actions.queueTask(new DestroyDraftTask(draftClientId: item.clientId))
@_view.selection.clear()