mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-08 21:55:54 +08:00
fix(trash/spam): New inAllMail filter applied to all mailbox views except trash and spam
This commit is contained in:
parent
b920cf83df
commit
96c0b5da29
6 changed files with 101 additions and 13 deletions
|
@ -20,6 +20,38 @@ describe 'Thread', ->
|
|||
iterations += 1
|
||||
console.log((Date.now() - start) / 1000.0 + "ms per 1000")
|
||||
|
||||
describe "inAllMail", ->
|
||||
describe "when the thread categoriesType is 'folders'", ->
|
||||
it "should return true", ->
|
||||
thread = new Thread(categoriesType: 'folders', categories: [new Category(name: 'inbox')])
|
||||
expect(thread.inAllMail).toBe(true)
|
||||
|
||||
# Unlike Gmail, this means half the thread is in trash and half is in sent.
|
||||
# It should still appear in results for "Sent"
|
||||
thread = new Thread(categoriesType: 'folders', categories: [new Category(name: 'sent'), new Category(name: 'trash')])
|
||||
expect(thread.inAllMail).toBe(true)
|
||||
|
||||
describe "when the thread categoriesType is 'labels'", ->
|
||||
it "should return true if the thread has an all category", ->
|
||||
thread = new Thread(categoriesType: 'labels', categories: [new Category(name: 'all')])
|
||||
expect(thread.inAllMail).toBe(true)
|
||||
|
||||
# thread is half in spam
|
||||
thread = new Thread(categoriesType: 'labels', categories: [new Category(name: 'all'), new Category(name: 'inbox'), new Category(name: 'spam')])
|
||||
expect(thread.inAllMail).toBe(true)
|
||||
|
||||
it "should return false if the thread has the spam category and no all mail", ->
|
||||
thread = new Thread(categoriesType: 'labels', categories: [new Category(name: 'sent'), new Category(name: 'spam')])
|
||||
expect(thread.inAllMail).toBe(false)
|
||||
|
||||
it "should return false if the thread has the trash category and no all mail", ->
|
||||
thread = new Thread(categoriesType: 'labels', categories: [new Category(name: 'sent'), new Category(name: 'trash')])
|
||||
expect(thread.inAllMail).toBe(false)
|
||||
|
||||
it "should return true if the thread has none of the above (assume all mail)", ->
|
||||
thread = new Thread(categoriesType: 'labels', categories: [new Category(name: 'inbox')])
|
||||
expect(thread.inAllMail).toBe(true)
|
||||
|
||||
describe 'sortedCategories', ->
|
||||
sortedForCategoryNames = (inputs) ->
|
||||
categories = _.map inputs, (i) ->
|
||||
|
|
|
@ -30,7 +30,7 @@ describe 'Utils', ->
|
|||
subject: 'Test 1234'
|
||||
|
||||
it "should serialize and de-serialize models correctly", ->
|
||||
expectedString = '[{"client_id":"local-1","account_id":"1","metadata":[],"subject":"Test 1234","participants":[{"client_id":"local-a","account_id":"1","name":"Juan","email":"juan@nylas.com","thirdPartyData":{},"id":"local-a"},{"client_id":"local-b","account_id":"1","name":"Ben","email":"ben@nylas.com","thirdPartyData":{},"id":"local-b"}],"id":"local-1","__constructorName":"Thread"}]'
|
||||
expectedString = '[{"client_id":"local-1","account_id":"1","metadata":[],"subject":"Test 1234","participants":[{"client_id":"local-a","account_id":"1","name":"Juan","email":"juan@nylas.com","thirdPartyData":{},"id":"local-a"},{"client_id":"local-b","account_id":"1","name":"Ben","email":"ben@nylas.com","thirdPartyData":{},"id":"local-b"}],"in_all_mail":true,"id":"local-1","__constructorName":"Thread"}]'
|
||||
|
||||
jsonString = JSON.stringify([@testThread], Utils.registeredObjectReplacer)
|
||||
expect(jsonString).toEqual(expectedString)
|
||||
|
@ -40,7 +40,7 @@ describe 'Utils', ->
|
|||
it "should re-inflate Models in places they're not explicitly declared types", ->
|
||||
b = new JSONBlob({id: "local-ThreadsToProcess", json: [@testThread]})
|
||||
jsonString = JSON.stringify(b, Utils.registeredObjectReplacer)
|
||||
expectedString = '{"client_id":"local-ThreadsToProcess","server_id":"local-ThreadsToProcess","json":[{"client_id":"local-1","account_id":"1","metadata":[],"subject":"Test 1234","participants":[{"client_id":"local-a","account_id":"1","name":"Juan","email":"juan@nylas.com","thirdPartyData":{},"id":"local-a"},{"client_id":"local-b","account_id":"1","name":"Ben","email":"ben@nylas.com","thirdPartyData":{},"id":"local-b"}],"id":"local-1","__constructorName":"Thread"}],"id":"local-ThreadsToProcess","__constructorName":"JSONBlob"}'
|
||||
expectedString = '{"client_id":"local-ThreadsToProcess","server_id":"local-ThreadsToProcess","json":[{"client_id":"local-1","account_id":"1","metadata":[],"subject":"Test 1234","participants":[{"client_id":"local-a","account_id":"1","name":"Juan","email":"juan@nylas.com","thirdPartyData":{},"id":"local-a"},{"client_id":"local-b","account_id":"1","name":"Ben","email":"ben@nylas.com","thirdPartyData":{},"id":"local-b"}],"in_all_mail":true,"id":"local-1","__constructorName":"Thread"}],"id":"local-ThreadsToProcess","__constructorName":"JSONBlob"}'
|
||||
|
||||
expect(jsonString).toEqual(expectedString)
|
||||
revived = JSON.parse(jsonString, Utils.registeredObjectReviver)
|
||||
|
|
|
@ -151,7 +151,34 @@ class OrCompositeMatcher extends Matcher
|
|||
wheres.push(matcher.whereSQL(klass))
|
||||
return "(" + wheres.join(" OR ") + ")"
|
||||
|
||||
class AndCompositeMatcher extends Matcher
|
||||
constructor: (@children) ->
|
||||
@
|
||||
|
||||
attribute: =>
|
||||
null
|
||||
|
||||
value: =>
|
||||
null
|
||||
|
||||
evaluate: (model) =>
|
||||
_.every @children, (matcher) -> matcher.evaluate(model)
|
||||
|
||||
joinSQL: (klass) =>
|
||||
joins = []
|
||||
for matcher in @children
|
||||
join = matcher.joinSQL(klass)
|
||||
joins.push(join) if join
|
||||
return joins
|
||||
|
||||
whereSQL: (klass) =>
|
||||
wheres = []
|
||||
for matcher in @children
|
||||
wheres.push(matcher.whereSQL(klass))
|
||||
return "(" + wheres.join(" AND ") + ")"
|
||||
|
||||
Matcher.muid = 0
|
||||
Matcher.Or = OrCompositeMatcher
|
||||
Matcher.And = AndCompositeMatcher
|
||||
|
||||
module.exports = Matcher
|
||||
|
|
|
@ -65,6 +65,9 @@ class Thread extends ModelWithMetadata
|
|||
modelKey: 'categories'
|
||||
itemClass: Category
|
||||
|
||||
'categoriesType': Attributes.String
|
||||
modelKey: 'categoriesType'
|
||||
|
||||
'participants': Attributes.Collection
|
||||
queryable: true
|
||||
joinOnField: 'email'
|
||||
|
@ -84,6 +87,19 @@ class Thread extends ModelWithMetadata
|
|||
modelKey: 'lastMessageSentTimestamp'
|
||||
jsonKey: 'last_message_sent_timestamp'
|
||||
|
||||
'inAllMail': Attributes.Boolean
|
||||
queryable: true
|
||||
modelKey: 'inAllMail'
|
||||
jsonKey: 'in_all_mail'
|
||||
|
||||
Object.defineProperty @attributes, "labels",
|
||||
enumerable: false
|
||||
get: -> @categories
|
||||
|
||||
Object.defineProperty @attributes, "folders",
|
||||
enumerable: false
|
||||
get: -> @categories
|
||||
|
||||
Object.defineProperty @prototype, "labels",
|
||||
enumerable: false
|
||||
get: -> @categories
|
||||
|
@ -94,13 +110,17 @@ class Thread extends ModelWithMetadata
|
|||
get: -> @categories
|
||||
set: (v) -> @categories = v
|
||||
|
||||
Object.defineProperty @attributes, "labels",
|
||||
Object.defineProperty @prototype, "inAllMail",
|
||||
enumerable: false
|
||||
get: -> @categories
|
||||
|
||||
Object.defineProperty @attributes, "folders",
|
||||
enumerable: false
|
||||
get: -> @categories
|
||||
get: ->
|
||||
if @categoriesType is 'labels'
|
||||
inAllMail = _.any @categories, (cat) -> cat.name is 'all'
|
||||
return true if inAllMail
|
||||
inTrashOrSpam = _.any @categories, (cat) -> cat.name is 'trash' or cat.name is 'spam'
|
||||
return true if not inTrashOrSpam
|
||||
return false
|
||||
else
|
||||
return true
|
||||
|
||||
@naturalSortOrder: ->
|
||||
Thread.attributes.lastMessageReceivedTimestamp.descending()
|
||||
|
@ -108,14 +128,19 @@ class Thread extends ModelWithMetadata
|
|||
@additionalSQLiteConfig:
|
||||
setup: ->
|
||||
['CREATE INDEX IF NOT EXISTS ThreadListIndex ON Thread(last_message_received_timestamp DESC, id)',
|
||||
'CREATE INDEX IF NOT EXISTS ThreadListSentIndex ON Thread(last_message_sent_timestamp DESC, id)',
|
||||
'CREATE INDEX IF NOT EXISTS ThreadStarIndex ON Thread(account_id, starred)']
|
||||
|
||||
fromJSON: (json) ->
|
||||
super(json)
|
||||
|
||||
value = json['labels'] ? json['folders']
|
||||
if value
|
||||
@categories = @constructor.attributes.categories.fromJSON(value)
|
||||
if json['folders']
|
||||
@categoriesType = 'folders'
|
||||
@categories = @constructor.attributes.categories.fromJSON(json['folders'])
|
||||
|
||||
if json['labels']
|
||||
@categoriesType = 'labels'
|
||||
@categories = @constructor.attributes.categories.fromJSON(json['labels'])
|
||||
|
||||
for attr in ['participants', 'categories']
|
||||
value = @[attr]
|
||||
|
|
|
@ -16,7 +16,7 @@ DatabaseTransaction = require './database-transaction'
|
|||
|
||||
{ipcRenderer} = require 'electron'
|
||||
|
||||
DatabaseVersion = 20
|
||||
DatabaseVersion = 21
|
||||
DatabasePhase =
|
||||
Setup: 'setup'
|
||||
Ready: 'ready'
|
||||
|
|
|
@ -213,7 +213,8 @@ class StarredMailboxPerspective extends MailboxPerspective
|
|||
threads: =>
|
||||
query = DatabaseStore.findAll(Thread).where([
|
||||
Thread.attributes.accountId.in(@accountIds),
|
||||
Thread.attributes.starred.equal(true)
|
||||
Thread.attributes.starred.equal(true),
|
||||
Thread.attributes.inAllMail.equal(true),
|
||||
]).limit(0)
|
||||
|
||||
return new MutableQuerySubscription(query, {asResultSet: true})
|
||||
|
@ -275,6 +276,9 @@ class CategoryMailboxPerspective extends MailboxPerspective
|
|||
if @isSent()
|
||||
query.order(Thread.attributes.lastMessageSentTimestamp.descending())
|
||||
|
||||
unless @categoriesSharedName() in ['sent', 'trash']
|
||||
query.where(inAllMail: true)
|
||||
|
||||
if @_categories.length > 1 and @accountIds.length < @_categories.length
|
||||
# The user has multiple categories in the same account selected, which
|
||||
# means our result set could contain multiple copies of the same threads
|
||||
|
|
Loading…
Add table
Reference in a new issue