mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-24 09:16:07 +08:00
afe77b27fb
Summary: Replaces `new Notification`-based HTML5 notifications with system native notifications on Mac OS X. This allows us to implement the "Reply" button in the notifications. This will also serve as the hook for native Windows notifications, which are unsupported in Chromium. Test Plan: Run tests Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D2199
139 lines
4.5 KiB
CoffeeScript
139 lines
4.5 KiB
CoffeeScript
_ = require 'underscore'
|
|
{Thread,
|
|
Actions,
|
|
MailViewFilter,
|
|
AccountStore,
|
|
CategoryStore,
|
|
SoundRegistry,
|
|
NativeNotifications,
|
|
DatabaseStore} = require 'nylas-exports'
|
|
|
|
module.exports =
|
|
|
|
config:
|
|
enabled:
|
|
type: 'boolean'
|
|
default: true
|
|
|
|
activate: ->
|
|
@unlisteners = []
|
|
@unlisteners.push Actions.didPassivelyReceiveNewModels.listen(@_onNewMailReceived, @)
|
|
@activationTime = Date.now()
|
|
@stack = []
|
|
@stackProcessTimer = null
|
|
|
|
deactivate: ->
|
|
fn() for fn in @unlisteners
|
|
|
|
serialize: ->
|
|
|
|
_notifyAll: ->
|
|
NativeNotifications.displayNotification
|
|
title: "#{@stack.length} Unread Messages",
|
|
tag: 'unread-update'
|
|
@stack = []
|
|
|
|
_notifyOne: ({message, thread}) ->
|
|
account = _.find AccountStore.items(), (a) -> a.id is message.accountId
|
|
from = message.from[0]?.displayName() ? "Unknown"
|
|
title = from
|
|
if message.subject and message.subject.length > 0
|
|
subtitle = message.subject
|
|
body = message.snippet
|
|
else
|
|
subtitle = message.snippet
|
|
body = null
|
|
|
|
notif = NativeNotifications.displayNotification
|
|
title: title
|
|
subtitle: subtitle
|
|
body: body
|
|
canReply: true
|
|
tag: 'unread-update'
|
|
onActivate: ({tag, response, activationType}) =>
|
|
if activationType is 'replied' and response and _.isString(response)
|
|
Actions.sendQuickReply({thread, message}, response)
|
|
else
|
|
atom.displayWindow()
|
|
if AccountStore.current().id isnt thread.accountId
|
|
Actions.selectAccountId(thread.accountId)
|
|
|
|
MailViewFilter filter = MailViewFilter.forCategory(thread.categoryNamed('inbox'))
|
|
Actions.focusMailView(filter)
|
|
Actions.setFocus(collection: 'thread', item: thread)
|
|
|
|
_notifyMessages: ->
|
|
if @stack.length >= 5
|
|
@_notifyAll()
|
|
else if @stack.length > 0
|
|
@_notifyOne(@stack.pop())
|
|
|
|
@stackProcessTimer = null
|
|
if @stack.length > 0
|
|
@stackProcessTimer = setTimeout(( => @_notifyMessages()), 2000)
|
|
|
|
# https://phab.nylas.com/D2188
|
|
_onNewMessagesMissingThreads: (messages) ->
|
|
setTimeout =>
|
|
threads = {}
|
|
for msg in messages
|
|
threads[msg.threadId] ?= DatabaseStore.find(Thread, msg.threadId)
|
|
Promise.props(threads).then (threads) =>
|
|
messages = _.filter messages, (msg) =>
|
|
threads[msg.threadId]?
|
|
if messages.length > 0
|
|
@_onNewMailReceived({message: messages, thread: _.values(threads)})
|
|
, 10000
|
|
|
|
_onNewMailReceived: (incoming) ->
|
|
new Promise (resolve, reject) =>
|
|
return resolve() if atom.config.get('core.notifications.enabled') is false
|
|
|
|
incomingMessages = incoming['message'] ? []
|
|
incomingThreads = incoming['thread'] ? []
|
|
|
|
# Filter for new messages that are not sent by the current user
|
|
newUnread = _.filter incomingMessages, (msg) =>
|
|
isUnread = msg.unread is true
|
|
isNew = msg.date?.valueOf() >= @activationTime
|
|
isFromMe = msg.isFromMe()
|
|
return isUnread and isNew and not isFromMe
|
|
|
|
return resolve() if newUnread.length is 0
|
|
|
|
# For each message, find it's corresponding thread. First, look to see
|
|
# if it's already in the `incoming` payload (sent via delta sync
|
|
# at the same time as the message.) If it's not, try loading it from
|
|
# the local cache.
|
|
#
|
|
# Note we may receive multiple unread msgs for the same thread.
|
|
# Using a map and ?= to avoid repeating work.
|
|
threads = {}
|
|
for msg in newUnread
|
|
threads[msg.threadId] ?= _.findWhere(incomingThreads, {id: msg.threadId})
|
|
threads[msg.threadId] ?= DatabaseStore.find(Thread, msg.threadId)
|
|
|
|
Promise.props(threads).then (threads) =>
|
|
# Filter new unread messages to just the ones in the inbox
|
|
newUnreadInInbox = _.filter newUnread, (msg) ->
|
|
threads[msg.threadId]?.categoryNamed('inbox')
|
|
|
|
# Filter messages that we can't decide whether to display or not
|
|
# since no associated Thread object has arrived yet.
|
|
newUnreadMissingThreads = _.filter newUnread, (msg) ->
|
|
not threads[msg.threadId]?
|
|
|
|
if newUnreadMissingThreads.length > 0
|
|
@_onNewMessagesMissingThreads(newUnreadMissingThreads)
|
|
|
|
return resolve() if newUnreadInInbox.length is 0
|
|
if atom.config.get("core.notifications.sounds")
|
|
SoundRegistry.playSound('new-mail')
|
|
|
|
for msg in newUnreadInInbox
|
|
@stack.push({message: msg, thread: threads[msg.threadId]})
|
|
if not @stackProcessTimer
|
|
@_notifyMessages()
|
|
|
|
resolve()
|