diff --git a/internal_packages/notifications/lib/headers/account-error-header.jsx b/internal_packages/notifications/lib/headers/account-error-header.jsx index 18360121b..c1ed9055c 100644 --- a/internal_packages/notifications/lib/headers/account-error-header.jsx +++ b/internal_packages/notifications/lib/headers/account-error-header.jsx @@ -51,16 +51,13 @@ export default class AccountErrorHeader extends React.Component { } _onCheckAgain = (event) => { - const errorAccounts = this.state.accounts.filter(a => a.hasSyncStateError()); this.setState({refreshing: true}); event.stopPropagation(); - IdentityStore.refreshStatus().finally(() => { - AccountStore.refreshHealthOfAccounts(errorAccounts.map(a => a.id)).finally(() => { - if (!this.mounted) { return; } - this.setState({refreshing: false}); - }); + IdentityStore.refreshIdentityAndAccounts().finally(() => { + if (!this.mounted) { return; } + this.setState({refreshing: false}); }); } diff --git a/internal_packages/notifications/spec/account-error-header-spec.jsx b/internal_packages/notifications/spec/account-error-header-spec.jsx index 6cbefa0ec..06c7edd86 100644 --- a/internal_packages/notifications/spec/account-error-header-spec.jsx +++ b/internal_packages/notifications/spec/account-error-header-spec.jsx @@ -20,12 +20,9 @@ describe("AccountErrorHeader", function AccountErrorHeaderTests() { it("allows the user to refresh the account", () => { const header = mount(); - spyOn(IdentityStore, 'refreshStatus').andReturn(Promise.resolve()); - spyOn(AccountStore, 'refreshHealthOfAccounts').andReturn(Promise.resolve()); + spyOn(IdentityStore, 'refreshIdentityAndAccounts').andReturn(Promise.resolve()); header.find('.action.refresh').simulate('click'); - expect(IdentityStore.refreshStatus).toHaveBeenCalled(); - advanceClock(); - expect(AccountStore.refreshHealthOfAccounts).toHaveBeenCalledWith(['A']); + expect(IdentityStore.refreshIdentityAndAccounts).toHaveBeenCalled(); }); it("allows the user to reconnect the account", () => { @@ -53,12 +50,9 @@ describe("AccountErrorHeader", function AccountErrorHeaderTests() { it("allows the user to refresh the accounts", () => { const header = mount(); - spyOn(IdentityStore, 'refreshStatus').andReturn(Promise.resolve()); - spyOn(AccountStore, 'refreshHealthOfAccounts').andReturn(Promise.resolve()); + spyOn(IdentityStore, 'refreshIdentityAndAccounts').andReturn(Promise.resolve()); header.find('.action.refresh').simulate('click'); - expect(IdentityStore.refreshStatus).toHaveBeenCalled(); - advanceClock(); - expect(AccountStore.refreshHealthOfAccounts).toHaveBeenCalledWith(['A', 'B']); + expect(IdentityStore.refreshIdentityAndAccounts).toHaveBeenCalled(); }); it("allows the user to open preferences", () => { diff --git a/internal_packages/preferences/lib/tabs/preferences-identity.jsx b/internal_packages/preferences/lib/tabs/preferences-identity.jsx index 016be7bc5..9292488ee 100644 --- a/internal_packages/preferences/lib/tabs/preferences-identity.jsx +++ b/internal_packages/preferences/lib/tabs/preferences-identity.jsx @@ -83,7 +83,7 @@ class PreferencesIdentity extends React.Component { _onRefresh = () => { this.setState({refreshing: true}); - IdentityStore.refreshStatus().finally(() => { + IdentityStore.refreshIdentityAndAccounts().finally(() => { this.setState({refreshing: false}); }); } diff --git a/spec/stores/account-store-spec.coffee b/spec/stores/account-store-spec.coffee index a1e03283b..1801d22c7 100644 --- a/spec/stores/account-store-spec.coffee +++ b/spec/stores/account-store-spec.coffee @@ -79,21 +79,6 @@ describe "AccountStore", -> expect(@instance.tokenForAccountId('A')).toEqual('A-TOKEN') expect(@instance.tokenForAccountId('B')).toEqual('B-TOKEN') - describe "in the work window and running on production", -> - it "should refresh the accounts", -> - spyOn(NylasEnv, 'isWorkWindow').andReturn(true) - @instance = new @constructor - spyOn(@instance, 'refreshHealthOfAccounts') - advanceClock(10000) - expect(@instance.refreshHealthOfAccounts).toHaveBeenCalledWith(['A', 'B']) - - describe "in the main window", -> - it "should not refresh the accounts", -> - @instance = new @constructor - spyOn(@instance, 'refreshHealthOfAccounts') - advanceClock(10000) - expect(@instance.refreshHealthOfAccounts).not.toHaveBeenCalled() - describe "accountForEmail", -> beforeEach -> @instance = new @constructor diff --git a/src/flux/stores/account-store.coffee b/src/flux/stores/account-store.coffee index 85b527f06..d24542ad7 100644 --- a/src/flux/stores/account-store.coffee +++ b/src/flux/stores/account-store.coffee @@ -26,11 +26,6 @@ class AccountStore extends NylasStore @listenTo Actions.updateAccount, @_onUpdateAccount @listenTo Actions.reorderAccount, @_onReorderAccount - if NylasEnv.isWorkWindow() and ['staging', 'production'].includes(NylasEnv.config.get('env')) - setTimeout( => - @refreshHealthOfAccounts(@_accounts.map((a) -> a.id)) - , 2000) - NylasEnv.config.onDidChange configVersionKey, (change) => # If we already have this version of the accounts config, it means we # are the ones who saved the change, and we don't need to reload. diff --git a/src/flux/stores/identity-store.es6 b/src/flux/stores/identity-store.es6 index 72446edb6..ba5643e10 100644 --- a/src/flux/stores/identity-store.es6 +++ b/src/flux/stores/identity-store.es6 @@ -7,6 +7,7 @@ import Moment from 'moment-timezone'; import Actions from '../actions'; import AccountStore from './account-store'; +import Utils from '../models/utils'; const configIdentityKey = "nylas.identity"; const keytarServiceName = 'Nylas'; @@ -35,13 +36,16 @@ class IdentityStore extends NylasStore { NylasEnv.config.onDidChange(configIdentityKey, () => { this._loadIdentity(); this.trigger(); + if (NylasEnv.isMainWindow()) { + this.refreshAccounts(); + } }); this._loadIdentity(); if (NylasEnv.isMainWindow() && ['staging', 'production'].includes(NylasEnv.config.get('env'))) { - setInterval(this.refreshStatus, 1000 * 60 * 60); - this.refreshStatus(); + setInterval(this.refreshIdentityAndAccounts, 1000 * 60 * 60); // 1 hour + this.refreshIdentityAndAccounts(); } } @@ -102,20 +106,28 @@ class IdentityStore extends NylasStore { return Math.max(0, requiredDayOfEpoch - nowDayOfEpoch); } - refreshStatus = () => { - return Promise.all([ - this.fetchIdentity(), - Promise.all(AccountStore.accounts().map((a) => - this.fetchSubscriptionRequiredDate(a)) - ).then((subscriptionRequiredDates) => { - this._subscriptionRequiredAfter = subscriptionRequiredDates.sort().shift(); - this.trigger(); - }), - ]).catch((err) => { + refreshIdentityAndAccounts = () => { + return this.fetchIdentity().then(() => + this.refreshAccounts() + ).catch((err) => { console.error(`Unable to refresh IdentityStore status: ${err.message}`) }); } + refreshAccounts = () => { + const accountIds = AccountStore.accounts().map((a) => a.id); + AccountStore.refreshHealthOfAccounts(accountIds); + + return Promise.all(AccountStore.accounts().map((a) => + this.fetchSubscriptionRequiredDate(a)) + ).then((subscriptionRequiredDates) => { + this._subscriptionRequiredAfter = subscriptionRequiredDates.sort().shift(); + this.trigger(); + }).catch((err) => { + console.error(`Unable to refresh IdentityStore accounts: ${err.message}`) + }) + } + /** * This passes utm_source, utm_campaign, and utm_content params to the * N1 billing site. Please reference: @@ -184,15 +196,29 @@ class IdentityStore extends NylasStore { fetchPath = (path) => { return new Promise((resolve, reject) => { - request({ + const requestId = Utils.generateTempId(); + const options = { method: 'GET', url: `${this.URLRoot}${path}`, + startTime: Date.now(), auth: { username: this._identity.token, password: '', sendImmediately: true, }, - }, (error, response = {}, body) => { + }; + + Actions.willMakeAPIRequest({ + request: options, + requestId: requestId, + }); + request(options, (error, response = {}, body) => { + Actions.didMakeAPIRequest({ + request: options, + statusCode: response.statusCode, + error: error, + requestId: requestId, + }); if (response.statusCode === 200) { try { return resolve(JSON.parse(body));