mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-19 11:06:31 +08:00
feat(babel6): Convert message.coffee to message.es6
This commit is contained in:
parent
4b6433a8cb
commit
8f4e30329c
21 changed files with 387 additions and 329 deletions
|
@ -1,6 +1,6 @@
|
|||
_ = require 'underscore'
|
||||
Contact = require '../../../src/flux/models/contact'
|
||||
Message = require '../../../src/flux/models/message'
|
||||
Message = require('../../../src/flux/models/message').default
|
||||
Thread = require('../../../src/flux/models/thread').default
|
||||
Category = require '../../../src/flux/models/category'
|
||||
CategoryStore = require '../../../src/flux/stores/category-store'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Reflux = require 'reflux'
|
||||
Actions = require '../src/flux/actions'
|
||||
Message = require '../src/flux/models/message'
|
||||
Message = require('../src/flux/models/message').default
|
||||
DatabaseStore = require '../src/flux/stores/database-store'
|
||||
AccountStore = require '../src/flux/stores/account-store'
|
||||
ActionBridge = require '../src/flux/action-bridge',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Utils = require "../../src/flux/models/utils"
|
||||
Message = require "../../src/flux/models/message"
|
||||
Message = require("../../src/flux/models/message").default
|
||||
Contact = require "../../src/flux/models/contact"
|
||||
|
||||
evan = new Contact
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
ModelQuery = require '../../src/flux/models/query'
|
||||
{Matcher} = require '../../src/flux/attributes'
|
||||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
Thread = require('../../src/flux/models/thread').default
|
||||
Account = require('../../src/flux/models/account').default
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
Thread = require('../../src/flux/models/thread').default
|
||||
Category = require '../../src/flux/models/category'
|
||||
{Utils} = require 'nylas-exports'
|
||||
|
|
|
@ -3,7 +3,7 @@ fs = require 'fs'
|
|||
Actions = require '../src/flux/actions'
|
||||
NylasAPI = require '../src/flux/nylas-api'
|
||||
Thread = require('../src/flux/models/thread').default
|
||||
Message = require '../src/flux/models/message'
|
||||
Message = require('../src/flux/models/message').default
|
||||
AccountStore = require '../src/flux/stores/account-store'
|
||||
DatabaseStore = require '../src/flux/stores/database-store'
|
||||
DatabaseTransaction = require '../src/flux/stores/database-transaction'
|
||||
|
@ -247,7 +247,7 @@ describe "NylasAPI", ->
|
|||
expect(models[0].id).toBe 'b'
|
||||
|
||||
describe "when updating models", ->
|
||||
Message = require '../src/flux/models/message'
|
||||
Message = require('../src/flux/models/message').default
|
||||
beforeEach ->
|
||||
@json = [
|
||||
{id: 'a', object: 'draft', unread: true}
|
||||
|
@ -305,9 +305,9 @@ describe "NylasAPI", ->
|
|||
"label": require('../src/flux/models/label')
|
||||
"folder": require('../src/flux/models/folder')
|
||||
"thread": require('../src/flux/models/thread').default
|
||||
"draft": require('../src/flux/models/message')
|
||||
"draft": require('../src/flux/models/message').default
|
||||
"account": require('../src/flux/models/account').default
|
||||
"message": require('../src/flux/models/message')
|
||||
"message": require('../src/flux/models/message').default
|
||||
"contact": require('../src/flux/models/contact')
|
||||
"calendar": require('../src/flux/models/calendar')
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
Actions = require '../../src/flux/actions'
|
||||
DatabaseStore = require '../../src/flux/stores/database-store'
|
||||
DatabaseTransaction = require '../../src/flux/stores/database-transaction'
|
||||
|
|
|
@ -3,7 +3,7 @@ path = require 'path'
|
|||
{shell} = require 'electron'
|
||||
NylasAPI = require '../../src/flux/nylas-api'
|
||||
File = require '../../src/flux/models/file'
|
||||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
FileDownloadStore = require '../../src/flux/stores/file-download-store'
|
||||
AccountStore = require '../../src/flux/stores/account-store'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
_ = require 'underscore'
|
||||
Thread = require('../../src/flux/models/thread').default
|
||||
Category = require '../../src/flux/models/category'
|
||||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
FocusedContentStore = require '../../src/flux/stores/focused-content-store'
|
||||
FocusedPerspectiveStore = require '../../src/flux/stores/focused-perspective-store'
|
||||
MessageStore = require '../../src/flux/stores/message-store'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
_ = require 'underscore'
|
||||
Folder = require '../../src/flux/models/folder'
|
||||
Thread = require('../../src/flux/models/thread').default
|
||||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
Actions = require '../../src/flux/actions'
|
||||
NylasAPI = require '../../src/flux/nylas-api'
|
||||
Query = require '../../src/flux/models/query'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
_ = require 'underscore'
|
||||
Label = require '../../src/flux/models/label'
|
||||
Thread = require('../../src/flux/models/thread').default
|
||||
Message = require '../../src/flux/models/message'
|
||||
Message = require('../../src/flux/models/message').default
|
||||
Actions = require '../../src/flux/actions'
|
||||
NylasAPI = require '../../src/flux/nylas-api'
|
||||
DatabaseStore = require '../../src/flux/stores/database-store'
|
||||
|
|
|
@ -1,305 +0,0 @@
|
|||
_ = require 'underscore'
|
||||
moment = require 'moment'
|
||||
|
||||
File = require './file'
|
||||
Utils = require './utils'
|
||||
Event = require './event'
|
||||
Category = require './category'
|
||||
Contact = require './contact'
|
||||
Attributes = require '../attributes'
|
||||
AccountStore = require '../stores/account-store'
|
||||
ModelWithMetadata = require('./model-with-metadata').default
|
||||
|
||||
###
|
||||
Public: The Message model represents a Message object served by the Nylas Platform API.
|
||||
For more information about Messages on the Nylas Platform, read the
|
||||
[Messages API Documentation](https://nylas.com/docs/api#messages)
|
||||
|
||||
Messages are a sub-object of threads. The content of a message is immutable (with the
|
||||
exception being drafts). Nylas does not support operations such as move or delete on
|
||||
individual messages; those operations should be performed on the message’s thread.
|
||||
All messages are part of a thread, even if that thread has only one message.
|
||||
|
||||
## Attributes
|
||||
|
||||
`to`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`cc`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`bcc`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`from`: {AttributeCollection} A collection of {Contact} objects.
|
||||
|
||||
`replyTo`: {AttributeCollection} A collection of {Contact} objects.
|
||||
|
||||
`date`: {AttributeDateTime} When the message was delivered. Queryable.
|
||||
|
||||
`subject`: {AttributeString} The subject of the thread. Queryable.
|
||||
|
||||
`snippet`: {AttributeString} A short, 140-character plain-text summary of the message body.
|
||||
|
||||
`unread`: {AttributeBoolean} True if the message is unread. Queryable.
|
||||
|
||||
`starred`: {AttributeBoolean} True if the message is starred. Queryable.
|
||||
|
||||
`draft`: {AttributeBoolean} True if the message is a draft. Queryable.
|
||||
|
||||
`version`: {AttributeNumber} The version number of the message. Message
|
||||
versions are used for drafts, and increment when attributes are changed.
|
||||
|
||||
`files`: {AttributeCollection} A set of {File} models representing
|
||||
the attachments on this thread.
|
||||
|
||||
`body`: {AttributeJoinedData} The HTML body of the message. You must specifically
|
||||
request this attribute when querying for a Message using the {{AttributeJoinedData::include}}
|
||||
method.
|
||||
|
||||
`pristine`: {AttributeBoolean} True if the message is a draft which has not been
|
||||
edited since it was created.
|
||||
|
||||
`threadId`: {AttributeString} The ID of the Message's parent {Thread}. Queryable.
|
||||
|
||||
`replyToMessageId`: {AttributeString} The ID of a {Message} that this message
|
||||
is in reply to.
|
||||
|
||||
This class also inherits attributes from {Model}
|
||||
|
||||
Section: Models
|
||||
###
|
||||
class Message extends ModelWithMetadata
|
||||
|
||||
@attributes: _.extend {}, ModelWithMetadata.attributes,
|
||||
|
||||
'to': Attributes.Collection
|
||||
modelKey: 'to'
|
||||
itemClass: Contact
|
||||
|
||||
'cc': Attributes.Collection
|
||||
modelKey: 'cc'
|
||||
itemClass: Contact
|
||||
|
||||
'bcc': Attributes.Collection
|
||||
modelKey: 'bcc'
|
||||
itemClass: Contact
|
||||
|
||||
'from': Attributes.Collection
|
||||
modelKey: 'from'
|
||||
itemClass: Contact
|
||||
|
||||
'replyTo': Attributes.Collection
|
||||
modelKey: 'replyTo'
|
||||
jsonKey: 'reply_to'
|
||||
itemClass: Contact
|
||||
|
||||
'date': Attributes.DateTime
|
||||
queryable: true
|
||||
modelKey: 'date'
|
||||
|
||||
'body': Attributes.JoinedData
|
||||
modelTable: 'MessageBody'
|
||||
modelKey: 'body'
|
||||
|
||||
'files': Attributes.Collection
|
||||
modelKey: 'files'
|
||||
itemClass: File
|
||||
|
||||
'uploads': Attributes.Object
|
||||
queryable: false
|
||||
modelKey: 'uploads'
|
||||
|
||||
'unread': Attributes.Boolean
|
||||
queryable: true
|
||||
modelKey: 'unread'
|
||||
|
||||
'events': Attributes.Collection
|
||||
modelKey: 'events'
|
||||
itemClass: Event
|
||||
|
||||
'starred': Attributes.Boolean
|
||||
queryable: true
|
||||
modelKey: 'starred'
|
||||
|
||||
'snippet': Attributes.String
|
||||
modelKey: 'snippet'
|
||||
|
||||
'threadId': Attributes.ServerId
|
||||
queryable: true
|
||||
modelKey: 'threadId'
|
||||
jsonKey: 'thread_id'
|
||||
|
||||
'subject': Attributes.String
|
||||
modelKey: 'subject'
|
||||
|
||||
'draft': Attributes.Boolean
|
||||
modelKey: 'draft'
|
||||
jsonKey: 'draft'
|
||||
queryable: true
|
||||
|
||||
'pristine': Attributes.Boolean
|
||||
modelKey: 'pristine'
|
||||
jsonKey: 'pristine'
|
||||
queryable: false
|
||||
|
||||
'version': Attributes.Number
|
||||
modelKey: 'version'
|
||||
queryable: true
|
||||
|
||||
'replyToMessageId': Attributes.ServerId
|
||||
modelKey: 'replyToMessageId'
|
||||
jsonKey: 'reply_to_message_id'
|
||||
|
||||
'categories': Attributes.Collection
|
||||
modelKey: 'categories'
|
||||
itemClass: Category
|
||||
|
||||
@naturalSortOrder: ->
|
||||
Message.attributes.date.ascending()
|
||||
|
||||
@additionalSQLiteConfig:
|
||||
setup: ->
|
||||
[
|
||||
# For thread view
|
||||
'CREATE INDEX IF NOT EXISTS MessageListThreadIndex ON Message(thread_id, date ASC)',
|
||||
|
||||
# For draft lookups
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS MessageDraftIndex ON Message(client_id)',
|
||||
|
||||
# Partial indexes for draft
|
||||
'CREATE INDEX IF NOT EXISTS MessageListDraftIndex ON Message(account_id, date DESC) WHERE draft = 1',
|
||||
'CREATE INDEX IF NOT EXISTS MessageListUnifiedDraftIndex ON Message(date DESC) WHERE draft = 1',
|
||||
|
||||
# MessageBody lookups
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS MessageBodyIndex ON MessageBody(id)'
|
||||
]
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@subject ||= ""
|
||||
@to ||= []
|
||||
@cc ||= []
|
||||
@bcc ||= []
|
||||
@from ||= []
|
||||
@replyTo ||= []
|
||||
@files ||= []
|
||||
@uploads ||= []
|
||||
@events ||= []
|
||||
@categories ||= []
|
||||
@
|
||||
|
||||
toJSON: (options) ->
|
||||
json = super(options)
|
||||
json.file_ids = @fileIds()
|
||||
json.object = 'draft' if @draft
|
||||
json.event_id = @events[0].serverId if (@events and @events.length)
|
||||
json
|
||||
|
||||
fromJSON: (json={}) ->
|
||||
super (json)
|
||||
|
||||
# Only change the `draft` bit if the incoming json has an `object`
|
||||
# property. Because of `DraftChangeSet`, it's common for incoming json
|
||||
# to be an empty hash. In this case we want to leave the pre-existing
|
||||
# draft bit alone.
|
||||
if json.object?
|
||||
@draft = (json.object is 'draft')
|
||||
|
||||
if json['folder']
|
||||
@categories = @constructor.attributes.categories.fromJSON([json['folder']])
|
||||
else if json['labels']
|
||||
@categories = @constructor.attributes.categories.fromJSON(json['labels'])
|
||||
|
||||
for attr in ['to', 'from', 'cc', 'bcc', 'files', 'categories']
|
||||
values = @[attr]
|
||||
continue unless values and values instanceof Array
|
||||
item.accountId = @accountId for item in values
|
||||
|
||||
return @
|
||||
|
||||
canReplyAll: ->
|
||||
{to, cc} = @participantsForReplyAll()
|
||||
to.length > 1 or cc.length > 0
|
||||
|
||||
# Public: Returns a set of uniqued message participants by combining the
|
||||
# `to`, `cc`, and `from` fields.
|
||||
participants: ->
|
||||
seen = {}
|
||||
all = []
|
||||
for contact in [].concat(@to, @cc, @from)
|
||||
continue unless contact.email
|
||||
key = contact.toString().trim().toLowerCase()
|
||||
continue if seen[key]
|
||||
seen[key] = true
|
||||
all.push(contact)
|
||||
all
|
||||
|
||||
# Public: Returns a hash with `to` and `cc` keys for authoring a new draft in
|
||||
# "reply all" to this message. This method takes into account whether the
|
||||
# message is from the current user, and also looks at the replyTo field.
|
||||
participantsForReplyAll: ->
|
||||
excludedFroms = @from.map (c) -> Utils.toEquivalentEmailForm(c.email)
|
||||
excludeMeAndFroms = (cc) ->
|
||||
_.reject cc, (p) ->
|
||||
p.isMe() or _.contains(excludedFroms, Utils.toEquivalentEmailForm(p.email))
|
||||
|
||||
to = null
|
||||
cc = null
|
||||
|
||||
if @isFromMe()
|
||||
to = @to
|
||||
cc = excludeMeAndFroms(@cc)
|
||||
else
|
||||
if @replyTo.length
|
||||
to = @replyTo
|
||||
else
|
||||
to = @from
|
||||
cc = excludeMeAndFroms([].concat(@to, @cc))
|
||||
|
||||
to = _.uniq to, (p) -> Utils.toEquivalentEmailForm(p.email)
|
||||
cc = _.uniq cc, (p) -> Utils.toEquivalentEmailForm(p.email)
|
||||
{to, cc}
|
||||
|
||||
# Public: Returns a hash with `to` and `cc` keys for authoring a new draft in
|
||||
# "reply" to this message. This method takes into account whether the
|
||||
# message is from the current user, and also looks at the replyTo field.
|
||||
participantsForReply: ->
|
||||
to = []
|
||||
cc = []
|
||||
|
||||
if @isFromMe()
|
||||
to = @to
|
||||
else if @replyTo.length
|
||||
to = @replyTo
|
||||
else
|
||||
to = @from
|
||||
|
||||
to = _.uniq to, (p) -> Utils.toEquivalentEmailForm(p.email)
|
||||
{to, cc}
|
||||
|
||||
# Public: Returns an {Array} of {File} IDs
|
||||
fileIds: ->
|
||||
_.map @files, (file) -> file.id
|
||||
|
||||
# Public: Returns true if this message is from the current user's email
|
||||
# address. In the future, this method will take into account all of the
|
||||
# user's email addresses and accounts.
|
||||
isFromMe: ->
|
||||
@from[0]?.isMe()
|
||||
|
||||
# Public: Returns a plaintext version of the message body using Chromium's
|
||||
# DOMParser. Use with care.
|
||||
plainTextBody: ->
|
||||
if (@body ? "").trim().length is 0 then return ""
|
||||
(new DOMParser()).parseFromString(@body, "text/html").body.innerText
|
||||
|
||||
fromContact: ->
|
||||
@from?[0] ? new Contact(name: 'Unknown', email: 'Unknown')
|
||||
|
||||
# Public: Returns the standard attribution line for this message,
|
||||
# localized for the current user.
|
||||
# ie "On Dec. 12th, 2015 at 4:00PM, Ben Gotow wrote:"
|
||||
replyAttributionLine: ->
|
||||
"On #{@formattedDate()}, #{@fromContact().toString()} wrote:"
|
||||
|
||||
formattedDate: -> moment(@date).format("MMM D YYYY, [at] h:mm a")
|
||||
|
||||
module.exports = Message
|
363
src/flux/models/message.es6
Normal file
363
src/flux/models/message.es6
Normal file
|
@ -0,0 +1,363 @@
|
|||
import _ from 'underscore'
|
||||
import moment from 'moment'
|
||||
|
||||
import File from './file'
|
||||
import Utils from './utils'
|
||||
import Event from './event'
|
||||
import Category from './category'
|
||||
import Contact from './contact'
|
||||
import Attributes from '../attributes'
|
||||
import ModelWithMetadata from './model-with-metadata'
|
||||
|
||||
/**
|
||||
Public: The Message model represents a Message object served by the Nylas Platform API.
|
||||
For more information about Messages on the Nylas Platform, read the
|
||||
[Messages API Documentation](https://nylas.com/docs/api#messages)
|
||||
|
||||
Messages are a sub-object of threads. The content of a message === immutable (with the
|
||||
exception being drafts). Nylas does not support operations such as move || delete on
|
||||
individual messages; those operations should be performed on the message’s thread.
|
||||
All messages are part of a thread, even if that thread has only one message.
|
||||
|
||||
## Attributes
|
||||
|
||||
`to`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`cc`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`bcc`: {AttributeCollection} A collection of {Contact} objects
|
||||
|
||||
`from`: {AttributeCollection} A collection of {Contact} objects.
|
||||
|
||||
`replyTo`: {AttributeCollection} A collection of {Contact} objects.
|
||||
|
||||
`date`: {AttributeDateTime} When the message was delivered. Queryable.
|
||||
|
||||
`subject`: {AttributeString} The subject of the thread. Queryable.
|
||||
|
||||
`snippet`: {AttributeString} A short, 140-character plain-text summary of the message body.
|
||||
|
||||
`unread`: {AttributeBoolean} True if the message === unread. Queryable.
|
||||
|
||||
`starred`: {AttributeBoolean} True if the message === starred. Queryable.
|
||||
|
||||
`draft`: {AttributeBoolean} True if the message === a draft. Queryable.
|
||||
|
||||
`version`: {AttributeNumber} The version number of the message. Message
|
||||
versions are used for drafts, && increment when attributes are changed.
|
||||
|
||||
`files`: {AttributeCollection} A set of {File} models representing
|
||||
the attachments on this thread.
|
||||
|
||||
`body`: {AttributeJoinedData} The HTML body of the message. You must specifically
|
||||
request this attribute when querying for a Message using the {{AttributeJoinedData::include}}
|
||||
method.
|
||||
|
||||
`pristine`: {AttributeBoolean} True if the message === a draft which has not been
|
||||
edited since it was created.
|
||||
|
||||
`threadId`: {AttributeString} The ID of the Message's parent {Thread}. Queryable.
|
||||
|
||||
`replyToMessageId`: {AttributeString} The ID of a {Message} that this message
|
||||
=== in reply to.
|
||||
|
||||
This class also inherits attributes from {Model}
|
||||
|
||||
Section: Models
|
||||
*/
|
||||
export default class Message extends ModelWithMetadata {
|
||||
|
||||
static attributes = Object.assign({}, ModelWithMetadata.attributes, {
|
||||
to: Attributes.Collection({
|
||||
modelKey: 'to',
|
||||
itemClass: Contact,
|
||||
}),
|
||||
|
||||
cc: Attributes.Collection({
|
||||
modelKey: 'cc',
|
||||
itemClass: Contact,
|
||||
}),
|
||||
|
||||
bcc: Attributes.Collection({
|
||||
modelKey: 'bcc',
|
||||
itemClass: Contact,
|
||||
}),
|
||||
|
||||
from: Attributes.Collection({
|
||||
modelKey: 'from',
|
||||
itemClass: Contact,
|
||||
}),
|
||||
|
||||
replyTo: Attributes.Collection({
|
||||
modelKey: 'replyTo',
|
||||
jsonKey: 'reply_to',
|
||||
itemClass: Contact,
|
||||
}),
|
||||
|
||||
date: Attributes.DateTime({
|
||||
queryable: true,
|
||||
modelKey: 'date',
|
||||
}),
|
||||
|
||||
body: Attributes.JoinedData({
|
||||
modelTable: 'MessageBody',
|
||||
modelKey: 'body',
|
||||
}),
|
||||
|
||||
files: Attributes.Collection({
|
||||
modelKey: 'files',
|
||||
itemClass: File,
|
||||
}),
|
||||
|
||||
uploads: Attributes.Object({
|
||||
queryable: false,
|
||||
modelKey: 'uploads',
|
||||
}),
|
||||
|
||||
unread: Attributes.Boolean({
|
||||
queryable: true,
|
||||
modelKey: 'unread',
|
||||
}),
|
||||
|
||||
events: Attributes.Collection({
|
||||
modelKey: 'events',
|
||||
itemClass: Event,
|
||||
}),
|
||||
|
||||
starred: Attributes.Boolean({
|
||||
queryable: true,
|
||||
modelKey: 'starred',
|
||||
}),
|
||||
|
||||
snippet: Attributes.String({
|
||||
modelKey: 'snippet',
|
||||
}),
|
||||
|
||||
threadId: Attributes.ServerId({
|
||||
queryable: true,
|
||||
modelKey: 'threadId',
|
||||
jsonKey: 'thread_id',
|
||||
}),
|
||||
|
||||
subject: Attributes.String({
|
||||
modelKey: 'subject',
|
||||
}),
|
||||
|
||||
draft: Attributes.Boolean({
|
||||
modelKey: 'draft',
|
||||
jsonKey: 'draft',
|
||||
queryable: true,
|
||||
}),
|
||||
|
||||
pristine: Attributes.Boolean({
|
||||
modelKey: 'pristine',
|
||||
jsonKey: 'pristine',
|
||||
queryable: false,
|
||||
}),
|
||||
|
||||
version: Attributes.Number({
|
||||
modelKey: 'version',
|
||||
queryable: true,
|
||||
}),
|
||||
|
||||
replyToMessageId: Attributes.ServerId({
|
||||
modelKey: 'replyToMessageId',
|
||||
jsonKey: 'reply_to_message_id',
|
||||
}),
|
||||
|
||||
categories: Attributes.Collection({
|
||||
modelKey: 'categories',
|
||||
itemClass: Category,
|
||||
}),
|
||||
});
|
||||
|
||||
static naturalSortOrder() {
|
||||
Message.attributes.date.ascending()
|
||||
}
|
||||
|
||||
static additionalSQLiteConfig() {
|
||||
return {
|
||||
setup: () =>
|
||||
[
|
||||
`CREATE INDEX IF NOT EXISTS MessageListThreadIndex ON Message(thread_id, date ASC)`,
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS MessageDraftIndex ON Message(client_id)`,
|
||||
`CREATE INDEX IF NOT EXISTS MessageListDraftIndex ON \
|
||||
Message(account_id, date DESC) WHERE draft = 1`,
|
||||
`CREATE INDEX IF NOT EXISTS MessageListUnifiedDraftIndex ON \
|
||||
Message(date DESC) WHERE draft = 1`,
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS MessageBodyIndex ON MessageBody(id)`,
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.subject = this.subject || ""
|
||||
this.to = this.to || []
|
||||
this.cc = this.cc || []
|
||||
this.bcc = this.bcc || []
|
||||
this.from = this.from || []
|
||||
this.replyTo = this.replyTo || []
|
||||
this.files = this.files || []
|
||||
this.uploads = this.uploads || []
|
||||
this.events = this.events || []
|
||||
this.categories = this.categories || []
|
||||
}
|
||||
|
||||
toJSON(options) {
|
||||
const json = super.toJSON(options)
|
||||
json.file_ids = this.fileIds()
|
||||
if (this.draft) {
|
||||
json.object = 'draft'
|
||||
}
|
||||
|
||||
if (this.events && this.events.length) {
|
||||
json.event_id = this.events[0].serverId
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
fromJSON(json = {}) {
|
||||
super.fromJSON(json)
|
||||
|
||||
// Only change the `draft` bit if the incoming json has an `object`
|
||||
// property. Because of `DraftChangeSet`, it's common for incoming json
|
||||
// to be an empty hash. In this case we want to leave the pre-existing
|
||||
// draft bit alone.
|
||||
if (json.object) {
|
||||
this.draft = (json.object === 'draft')
|
||||
}
|
||||
|
||||
if (json.folder) {
|
||||
this.categories = this.constructor.attributes.categories.fromJSON([json.folder])
|
||||
} else if (json.labels) {
|
||||
this.categories = this.constructor.attributes.categories.fromJSON(json.labels)
|
||||
}
|
||||
|
||||
for (const attr of ['to', 'from', 'cc', 'bcc', 'files', 'categories']) {
|
||||
const values = this[attr]
|
||||
if (!(values && values instanceof Array)) {
|
||||
continue;
|
||||
}
|
||||
for (const item of values) {
|
||||
item.accountId = this.accountId
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
canReplyAll() {
|
||||
const {to, cc} = this.participantsForReplyAll()
|
||||
return to.length > 1 || cc.length > 0
|
||||
}
|
||||
|
||||
// Public: Returns a set of uniqued message participants by combining the
|
||||
// `to`, `cc`, && `from` fields.
|
||||
participants() {
|
||||
const seen = {}
|
||||
const all = []
|
||||
for (const contact of [].concat(this.to, this.cc, this.from)) {
|
||||
if (!contact.email) {
|
||||
continue
|
||||
}
|
||||
const key = contact.toString().trim().toLowerCase()
|
||||
if (seen[key]) {
|
||||
continue;
|
||||
}
|
||||
seen[key] = true
|
||||
all.push(contact)
|
||||
}
|
||||
return all
|
||||
}
|
||||
|
||||
// Public: Returns a hash with `to` && `cc` keys for authoring a new draft in
|
||||
// "reply all" to this message. This method takes into account whether the
|
||||
// message === from the current user, && also looks at the replyTo field.
|
||||
participantsForReplyAll() {
|
||||
const excludedFroms = this.from.map((c) =>
|
||||
Utils.toEquivalentEmailForm(c.email)
|
||||
);
|
||||
|
||||
const excludeMeAndFroms = (cc) =>
|
||||
_.reject(cc, (p) =>
|
||||
p.isMe() || _.contains(excludedFroms, Utils.toEquivalentEmailForm(p.email))
|
||||
);
|
||||
|
||||
let to = null
|
||||
let cc = null
|
||||
|
||||
if (this.isFromMe()) {
|
||||
to = this.to
|
||||
cc = excludeMeAndFroms(this.cc)
|
||||
} else {
|
||||
if (this.replyTo.length) {
|
||||
to = this.replyTo
|
||||
} else {
|
||||
to = this.from
|
||||
}
|
||||
cc = excludeMeAndFroms([].concat(this.to, this.cc))
|
||||
}
|
||||
|
||||
to = _.uniq(to, (p) => Utils.toEquivalentEmailForm(p.email))
|
||||
cc = _.uniq(cc, (p) => Utils.toEquivalentEmailForm(p.email))
|
||||
return {to, cc}
|
||||
}
|
||||
|
||||
// Public: Returns a hash with `to` && `cc` keys for authoring a new draft in
|
||||
// "reply" to this message. This method takes into account whether the
|
||||
// message === from the current user, && also looks at the replyTo field.
|
||||
participantsForReply() {
|
||||
let to = []
|
||||
const cc = []
|
||||
|
||||
if (this.isFromMe()) {
|
||||
to = this.to
|
||||
} else if (this.replyTo.length) {
|
||||
to = this.replyTo
|
||||
} else {
|
||||
to = this.from
|
||||
}
|
||||
|
||||
to = _.uniq(to, (p) => Utils.toEquivalentEmailForm(p.email))
|
||||
return {to, cc}
|
||||
}
|
||||
|
||||
// Public: Returns an {Array} of {File} IDs
|
||||
fileIds() {
|
||||
return _.map(this.files, (file) => file.id)
|
||||
}
|
||||
|
||||
// Public: Returns true if this message === from the current user's email
|
||||
// address. In the future, this method will take into account all of the
|
||||
// user's email addresses && accounts.
|
||||
isFromMe() {
|
||||
return ((this.from[0] || {}).isMe || (() => {}))()
|
||||
}
|
||||
|
||||
// Public: Returns a plaintext version of the message body using Chromium's
|
||||
// DOMParser. Use with care.
|
||||
plainTextBody() {
|
||||
if ((this.body || "").trim().length === 0) {
|
||||
return ""
|
||||
}
|
||||
return (new DOMParser()).parseFromString(this.body, "text/html").body.innerText
|
||||
}
|
||||
|
||||
fromContact() {
|
||||
return ((this.from || [])[0] || new Contact({name: 'Unknown', email: 'Unknown'}))
|
||||
}
|
||||
|
||||
// Public: Returns the standard attribution line for this message,
|
||||
// localized for the current user.
|
||||
// ie "On Dec. 12th, 2015 at 4:00PM, Ben Gotow wrote:"
|
||||
replyAttributionLine() {
|
||||
return "On #{this.formattedDate()}, #{this.fromContact().toString()} wrote:"
|
||||
}
|
||||
|
||||
formattedDate() {
|
||||
return moment(this.date).format("MMM D YYYY, [at] h:mm a")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ request = require 'request'
|
|||
NylasLongConnection = require('./nylas-long-connection').default
|
||||
Utils = require './models/utils'
|
||||
Account = require('./models/account').default
|
||||
Message = require './models/message'
|
||||
Message = require('./models/message').default
|
||||
Actions = require './actions'
|
||||
{APIError} = require './errors'
|
||||
PriorityUICoordinator = require '../priority-ui-coordinator'
|
||||
|
@ -350,9 +350,9 @@ class NylasAPI
|
|||
"label": require('./models/label')
|
||||
"folder": require('./models/folder')
|
||||
"thread": require('./models/thread').default
|
||||
"draft": require('./models/message')
|
||||
"draft": require('./models/message').default
|
||||
"account": require('./models/account').default
|
||||
"message": require('./models/message')
|
||||
"message": require('./models/message').default
|
||||
"contact": require('./models/contact')
|
||||
"calendar": require('./models/calendar')
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ class AccountStore extends NylasStore
|
|||
_importFakeData: (dir) =>
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
Message = require '../models/message'
|
||||
Message = require('../models/message').default
|
||||
Account = require('../models/account').default
|
||||
Thread = require('../models/thread').default
|
||||
Label = require '../models/label'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Message = require '../models/message'
|
||||
Message = require('../models/message').default
|
||||
Actions = require '../actions'
|
||||
DatabaseStore = require './database-store'
|
||||
ExtensionRegistry = require('../../extension-registry')
|
||||
|
|
|
@ -13,7 +13,7 @@ SanitizeTransformer = require '../../services/sanitize-transformer'
|
|||
|
||||
Thread = require('../models/thread').default
|
||||
Contact = require '../models/contact'
|
||||
Message = require '../models/message'
|
||||
Message = require('../models/message').default
|
||||
Utils = require '../models/utils'
|
||||
MessageUtils = require '../models/message-utils'
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ DestroyDraftTask = require('../tasks/destroy-draft-task').default
|
|||
|
||||
Thread = require('../models/thread').default
|
||||
Contact = require '../models/contact'
|
||||
Message = require '../models/message'
|
||||
Message = require('../models/message').default
|
||||
Actions = require '../actions'
|
||||
|
||||
TaskQueue = require './task-queue'
|
||||
|
|
|
@ -5,7 +5,7 @@ mkdirp = require 'mkdirp'
|
|||
NylasStore = require 'nylas-store'
|
||||
Actions = require '../actions'
|
||||
Utils = require '../models/utils'
|
||||
Message = require '../models/message'
|
||||
Message = require('../models/message').default
|
||||
DraftStore = require './draft-store'
|
||||
DatabaseStore = require './database-store'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
NylasStore = require "nylas-store"
|
||||
Actions = require "../actions"
|
||||
Message = require "../models/message"
|
||||
Message = require("../models/message").default
|
||||
Thread = require("../models/thread").default
|
||||
Utils = require '../models/utils'
|
||||
DatabaseStore = require "./database-store"
|
||||
|
|
|
@ -4,7 +4,7 @@ Task = require('./flux/tasks/task').default
|
|||
Actions = require './flux/actions'
|
||||
Category = require './flux/models/category'
|
||||
Thread = require('./flux/models/thread').default
|
||||
Message = require './flux/models/message'
|
||||
Message = require('./flux/models/message').default
|
||||
AccountStore = require './flux/stores/account-store'
|
||||
DatabaseStore = require './flux/stores/database-store'
|
||||
TaskQueueStatusStore = require './flux/stores/task-queue-status-store'
|
||||
|
|
Loading…
Add table
Reference in a new issue