Mailspring/app/internal_packages/activity-list/lib/activity-list-store.jsx
2017-09-26 11:36:58 -07:00

227 lines
6.9 KiB
JavaScript

import NylasStore from 'nylas-store';
import {
Actions,
Thread,
DatabaseStore,
NativeNotifications,
FocusedPerspectiveStore,
} from 'nylas-exports';
import ActivityListActions from './activity-list-actions';
import ActivityDataSource from './activity-data-source';
import { pluginFor } from './plugin-helpers';
class ActivityListStore extends NylasStore {
activate() {
this.listenTo(ActivityListActions.resetSeen, this._onResetSeen);
this.listenTo(FocusedPerspectiveStore, this._updateActivity);
const start = () => this._getActivity();
if (AppEnv.inSpecMode()) {
start();
} else {
setTimeout(start, 2000);
}
}
deactivate() {
// todo
}
actions() {
return this._actions;
}
unreadCount() {
if (this._unreadCount < 1000) {
return this._unreadCount;
} else if (!this._unreadCount) {
return null;
}
return '999+';
}
hasBeenViewed(action) {
if (!AppEnv.savedState.activityListViewed) return false;
return action.timestamp < AppEnv.savedState.activityListViewed;
}
focusThread(threadId) {
AppEnv.displayWindow();
Actions.closePopover();
DatabaseStore.find(Thread, threadId).then(thread => {
if (!thread) {
AppEnv.reportError(
new Error(`ActivityListStore::focusThread: Can't find thread`, { threadId })
);
AppEnv.showErrorDialog(`Can't find the selected thread in your mailbox`);
return;
}
Actions.ensureCategoryIsFocused('sent', thread.accountId);
Actions.setFocus({ collection: 'thread', item: thread });
});
}
getRecipient(recipientEmail, recipients) {
if (recipientEmail) {
for (const recipient of recipients) {
if (recipientEmail === recipient.email) {
return recipient;
}
}
} else if (recipients.length === 1) {
return recipients[0];
}
return null;
}
_dataSource() {
return new ActivityDataSource();
}
_onResetSeen() {
AppEnv.savedState.activityListViewed = Date.now() / 1000;
this._unreadCount = 0;
this.trigger();
}
_getActivity() {
const dataSource = this._dataSource();
this._subscription = dataSource
.buildObservable({
openTrackingId: AppEnv.packages.pluginIdFor('open-tracking'),
linkTrackingId: AppEnv.packages.pluginIdFor('link-tracking'),
messageLimit: 500,
})
.subscribe(messages => {
this._messages = messages;
this._updateActivity();
});
}
_updateActivity() {
this._actions = this._messages ? this._getActions(this._messages) : [];
this.trigger();
}
_getActions(messages) {
let actions = [];
this._notifications = [];
this._unreadCount = 0;
const sidebarAccountIds = FocusedPerspectiveStore.sidebarAccountIds();
for (const message of messages) {
if (sidebarAccountIds.length > 1 || message.accountId === sidebarAccountIds[0]) {
const openTrackingId = AppEnv.packages.pluginIdFor('open-tracking');
const linkTrackingId = AppEnv.packages.pluginIdFor('link-tracking');
if (
message.metadataForPluginId(openTrackingId) ||
message.metadataForPluginId(linkTrackingId)
) {
actions = actions.concat(this._openActionsForMessage(message));
actions = actions.concat(this._linkActionsForMessage(message));
}
}
}
if (!this._lastNotified) this._lastNotified = {};
for (const notification of this._notifications) {
const lastNotified = this._lastNotified[notification.threadId];
const { notificationInterval } = pluginFor(notification.pluginId);
if (!lastNotified || lastNotified < Date.now() - notificationInterval) {
NativeNotifications.displayNotification(notification.data);
this._lastNotified[notification.threadId] = Date.now();
}
}
const d = new Date();
this._lastChecked = d.getTime() / 1000;
actions = actions.sort((a, b) => b.timestamp - a.timestamp);
// For performance reasons, only display the last 100 actions
if (actions.length > 100) {
actions.length = 100;
}
return actions;
}
_openActionsForMessage(message) {
const openTrackingId = AppEnv.packages.pluginIdFor('open-tracking');
const openMetadata = message.metadataForPluginId(openTrackingId);
const recipients = message.to.concat(message.cc, message.bcc);
const actions = [];
if (openMetadata) {
if (openMetadata.open_count > 0) {
for (const open of openMetadata.open_data) {
const recipient = this.getRecipient(open.recipient, recipients);
if (open.timestamp > this._lastChecked) {
this._notifications.push({
pluginId: openTrackingId,
threadId: message.threadId,
data: {
title: 'New open',
subtitle: `${recipient
? recipient.displayName()
: 'Someone'} just opened ${message.subject}`,
canReply: false,
tag: 'message-open',
onActivate: () => {
this.focusThread(message.threadId);
},
},
});
}
if (!this.hasBeenViewed(open)) this._unreadCount += 1;
actions.push({
messageId: message.id,
threadId: message.threadId,
title: message.subject,
recipient: recipient,
pluginId: openTrackingId,
timestamp: open.timestamp,
});
}
}
}
return actions;
}
_linkActionsForMessage(message) {
const linkTrackingId = AppEnv.packages.pluginIdFor('link-tracking');
const linkMetadata = message.metadataForPluginId(linkTrackingId);
const recipients = message.to.concat(message.cc, message.bcc);
const actions = [];
if (linkMetadata && linkMetadata.links) {
for (const link of linkMetadata.links) {
for (const click of link.click_data) {
const recipient = this.getRecipient(click.recipient, recipients);
if (click.timestamp > this._lastChecked) {
this._notifications.push({
pluginId: linkTrackingId,
threadId: message.threadId,
data: {
title: 'New click',
subtitle: `${recipient
? recipient.displayName()
: 'Someone'} just clicked ${link.url}.`,
canReply: false,
tag: 'link-open',
onActivate: () => {
this.focusThread(message.threadId);
},
},
});
}
if (!this.hasBeenViewed(click)) this._unreadCount += 1;
actions.push({
messageId: message.id,
threadId: message.threadId,
title: link.url,
recipient: recipient,
pluginId: linkTrackingId,
timestamp: click.timestamp,
});
}
}
}
return actions;
}
}
export default new ActivityListStore();