- _renderTaskActivityItems: =>
- summary = {}
-
- @state.tasks.map (task) ->
- label = task.label?()
- return unless label
- summary[label] ?= 0
- summary[label] += task.numberOfImpactedItems()
-
- _.pairs(summary).map ([label, count]) ->
-
-
- ({new Number(count).toLocaleString()})
- {label}
-
-
-
_onDataChanged: =>
@setState(@_getStateFromStores())
diff --git a/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx b/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx
index aba59866c..dfe560ebc 100644
--- a/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx
+++ b/internal_packages/notifications/lib/sidebar/initial-sync-activity.jsx
@@ -1,7 +1,6 @@
import _ from 'underscore';
import _str from 'underscore.string';
-import classNames from 'classnames';
-import {Utils, Actions, AccountStore, NylasSyncStatusStore, React} from 'nylas-exports';
+import {Utils, AccountStore, NylasSyncStatusStore, React} from 'nylas-exports';
const MONTH_SHORT_FORMATS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
@@ -12,7 +11,6 @@ export default class InitialSyncActivity extends React.Component {
constructor(props) {
super(props);
this.state = {
- isExpanded: false,
syncState: NylasSyncStatusStore.getSyncState(),
syncProgress: NylasSyncStatusStore.getSyncProgress(),
}
@@ -21,10 +19,7 @@ export default class InitialSyncActivity extends React.Component {
componentDidMount() {
this.mounted = true;
- this.unsubs = [
- NylasSyncStatusStore.listen(this.onDataChanged),
- Actions.expandInitialSyncState.listen(this.showExpandedState),
- ]
+ this.unsub = NylasSyncStatusStore.listen(this.onDataChanged)
}
shouldComponentUpdate(nextProps, nextState) {
@@ -33,9 +28,7 @@ export default class InitialSyncActivity extends React.Component {
}
componentWillUnmount() {
- if (this.unsubs) {
- this.unsubs.forEach((unsub) => unsub())
- }
+ this.unsub();
this.mounted = false;
}
@@ -45,24 +38,42 @@ export default class InitialSyncActivity extends React.Component {
this.setState({syncState, syncProgress});
}
- hideExpandedState = () => {
- this.setState({isExpanded: false});
- }
-
- showExpandedState = () => {
- if (!this.state.isExpanded) {
- this.setState({isExpanded: true});
+ renderFolderProgress(name, progress, oldestProcessedDate) {
+ let status = 'busy';
+ let progressLabel = 'In Progress'
+ let syncedThrough = 'Syncing this past month';
+ if (progress === 1) {
+ status = 'complete';
+ progressLabel = '';
+ syncedThrough = 'Up to date'
} else {
- this.setState({blink: true});
- setTimeout(() => {
- if (this.mounted) {
- this.setState({blink: false});
+ let month = oldestProcessedDate.getMonth();
+ let year = oldestProcessedDate.getFullYear();
+ const currentDate = new Date();
+ if (month !== currentDate.getMonth() || year !== currentDate.getFullYear()) {
+ // We're currently syncing in `month`, which mean's we've synced through all
+ // of the month *after* it.
+ month++;
+ if (month === 12) {
+ month = 0;
+ year++;
}
- }, 1000)
+ syncedThrough = `Synced through ${MONTH_SHORT_FORMATS[month]} ${year}`;
+ }
}
+
+ return (
+
+ {_str.titleize(name)} {progressLabel}
+
+ )
}
- renderExpandedSyncState() {
+ render() {
+ if (!AccountStore.accountsAreSyncing() || this.state.syncProgress.progress === 1) {
+ return false;
+ }
+
let maxHeight = 0;
let accounts = _.map(this.state.syncState, (accountSyncState, accountId) => {
const account = _.findWhere(AccountStore.accounts(), {id: accountId});
@@ -101,70 +112,9 @@ export default class InitialSyncActivity extends React.Component {
key="expanded-sync-state"
style={{maxHeight: `${maxHeight + 500}px`}}
>
-
- Hide
-
{accounts}
)
}
- renderFolderProgress(name, progress, oldestProcessedDate) {
- let status = 'busy';
- let progressLabel = 'In Progress'
- let syncedThrough = 'Syncing this past month';
- if (progress === 1) {
- status = 'complete';
- progressLabel = '';
- syncedThrough = 'Up to date'
- } else {
- let month = oldestProcessedDate.getMonth();
- let year = oldestProcessedDate.getFullYear();
- const currentDate = new Date();
- if (month !== currentDate.getMonth() || year !== currentDate.getFullYear()) {
- // We're currently syncing in `month`, which mean's we've synced through all
- // of the month *after* it.
- month++;
- if (month === 12) {
- month = 0;
- year++;
- }
- syncedThrough = `Synced through ${MONTH_SHORT_FORMATS[month]} ${year}`;
- }
- }
-
- return (
-
- {_str.titleize(name)} {progressLabel}
-
- )
- }
-
- render() {
- if (!AccountStore.accountsAreSyncing()) {
- return false;
- }
-
- const {syncProgress: {progress}} = this.state
- if (progress === 1) {
- return false;
- }
-
- const classSet = classNames({
- 'item': true,
- 'expanded-sync': this.state.isExpanded,
- 'blink': this.state.blink,
- });
-
- return (
- (this.setState({isExpanded: !this.state.isExpanded}))}
- >
-
Syncing your mailbox
- {this.state.isExpanded ? this.renderExpandedSyncState() : false}
-
- )
- }
}
diff --git a/internal_packages/notifications/lib/sidebar/sync-activity.jsx b/internal_packages/notifications/lib/sidebar/sync-activity.jsx
new file mode 100644
index 000000000..b4a1f4f96
--- /dev/null
+++ b/internal_packages/notifications/lib/sidebar/sync-activity.jsx
@@ -0,0 +1,97 @@
+import classNames from 'classnames';
+import {Actions, React, Utils} from 'nylas-exports';
+
+import InitialSyncActivity from './initial-sync-activity';
+import SyncbackActivity from './syncback-activity';
+
+export default class SyncActivity extends React.Component {
+
+ static propTypes = {
+ initialSync: React.PropTypes.bool,
+ syncbackTasks: React.PropTypes.array,
+ }
+
+ constructor() {
+ super()
+ this.state = {
+ expanded: false,
+ blink: false,
+ }
+ this.mounted = false;
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+ this.unsub = Actions.expandInitialSyncState.listen(this.showExpandedState);
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return !Utils.isEqualReact(nextProps, this.props) ||
+ !Utils.isEqualReact(nextState, this.state);
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ this.unsub();
+ }
+
+ showExpandedState = () => {
+ if (!this.state.expanded) {
+ this.setState({expanded: true});
+ } else {
+ this.setState({blink: true});
+ setTimeout(() => {
+ if (this.mounted) {
+ this.setState({blink: false});
+ }
+ }, 1000)
+ }
+ }
+
+ hideExpandedState = () => {
+ this.setState({expanded: false});
+ }
+
+ _renderInitialSync() {
+ if (!this.props.initialSync) { return false; }
+ return
+ }
+
+ _renderSyncbackTasks() {
+ return
+ }
+
+ _renderExpandedDetails() {
+ return (
+
+
Hide
+ {this._renderSyncbackTasks()}
+ {this._renderInitialSync()}
+
+ )
+ }
+
+ render() {
+ const {initialSync, syncbackTasks} = this.props;
+ if (!initialSync && (!syncbackTasks || syncbackTasks.length === 0)) {
+ return false;
+ }
+
+ const classSet = classNames({
+ 'item': true,
+ 'expanded-sync': this.state.expanded,
+ 'blink': this.state.blink,
+ });
+
+ return (
+ (this.setState({expanded: !this.state.expanded}))}
+ >
+
Syncing your mailbox
+ {this.state.expanded ? this._renderExpandedDetails() : false}
+
+ )
+ }
+}
diff --git a/internal_packages/notifications/lib/sidebar/syncback-activity.jsx b/internal_packages/notifications/lib/sidebar/syncback-activity.jsx
new file mode 100644
index 000000000..2f6875fe8
--- /dev/null
+++ b/internal_packages/notifications/lib/sidebar/syncback-activity.jsx
@@ -0,0 +1,55 @@
+import _ from 'underscore';
+import {React, Utils} from 'nylas-exports';
+
+export default class SyncbackActivity extends React.Component {
+ static propTypes = {
+ syncbackTasks: React.PropTypes.array,
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return !Utils.isEqualReact(nextProps, this.props) ||
+ !Utils.isEqualReact(nextState, this.state);
+ }
+
+ render() {
+ const {syncbackTasks} = this.props;
+ if (!syncbackTasks || syncbackTasks.length === 0) { return false; }
+
+ const counts = {}
+ this.props.syncbackTasks.forEach((task) => {
+ const label = task.label ? task.label() : null;
+ if (!label) { return; }
+ if (!counts[label]) {
+ counts[label] = 0;
+ }
+ counts[label] += +task.numberOfImpactedItems()
+ });
+
+ const items = _.pairs(counts).map(([label, count]) => {
+ return (
+
+
+ ({count.toLocaleString()})
+ {label}
+
+
+ )
+ });
+
+ if (items.length === 0) {
+ items.push(
+
+ )
+ }
+
+ return (
+
+ {items}
+
+ )
+ }
+}
diff --git a/internal_packages/notifications/stylesheets/notifications.less b/internal_packages/notifications/stylesheets/notifications.less
index 2aef7b5a5..dc4426b1b 100644
--- a/internal_packages/notifications/stylesheets/notifications.less
+++ b/internal_packages/notifications/stylesheets/notifications.less
@@ -5,12 +5,6 @@
order: 2;
z-index: 2;
overflow-y: auto;
-
- &.sidebar-activity-empty {
- position: absolute;
- bottom: 0;
- width: 100%;
- }
}
.sidebar-activity {
@@ -24,12 +18,14 @@
box-shadow:inset 0 1px 0 @border-color-divider;
&:hover { cursor: default }
+
.item {
- border-bottom:1px solid @border-color-divider;
&:hover { cursor: default }
+ .clickable { cursor: pointer; }
.inner {
padding: @padding-large-vertical @padding-base-horizontal @padding-large-vertical @padding-base-horizontal;
+ border-bottom: 1px solid rgba(0,0,0,0.1);
}
.inner::after {
content: '...';
@@ -115,10 +111,11 @@
color: @text-color-subtle;
}
.close-expanded {
- display: block;
- text-align: right;
- border-top: 1px solid rgba(0,0,0,0.1);
- padding: @padding-large-vertical @padding-base-horizontal 0 @padding-base-horizontal;
+ padding: @padding-large-vertical @padding-base-horizontal;
+ position: absolute;
+ top: 0;
+ right: 0;
+ cursor: pointer;
}
}
diff --git a/src/K2 b/src/K2
index ae9d6f75d..32c1caa6c 160000
--- a/src/K2
+++ b/src/K2
@@ -1 +1 @@
-Subproject commit ae9d6f75defbab23fe5859d313132125844f5266
+Subproject commit 32c1caa6c6f38e60e15d1919e71559aec9c19ffc
diff --git a/src/flux/tasks/change-unread-task.es6 b/src/flux/tasks/change-unread-task.es6
index 93735b90c..70f800bfa 100644
--- a/src/flux/tasks/change-unread-task.es6
+++ b/src/flux/tasks/change-unread-task.es6
@@ -10,6 +10,10 @@ export default class ChangeUnreadTask extends ChangeMailTask {
this.unread = options.unread;
}
+ label() {
+ return this.unread ? "Marking as unread" : "Marking as read";
+ }
+
description() {
const count = this.threads.length;
const type = count > 1 ? 'threads' : 'thread';
diff --git a/src/flux/tasks/ensure-message-in-sent-folder-task.es6 b/src/flux/tasks/ensure-message-in-sent-folder-task.es6
index 082adb5f8..269ab8cbd 100644
--- a/src/flux/tasks/ensure-message-in-sent-folder-task.es6
+++ b/src/flux/tasks/ensure-message-in-sent-folder-task.es6
@@ -13,6 +13,10 @@ export default class EnsureMessageInSentFolderTask extends Task {
this.sentPerRecipient = opts.sentPerRecipient;
}
+ label() {
+ return "Saving to sent folder";
+ }
+
isDependentOnTask(other) {
return (other instanceof SendDraftTask) && (other.message) && (other.message.clientId === this.message.clientId);
}