diff --git a/app/internal_packages/composer-templates/lib/template-store.es6 b/app/internal_packages/composer-templates/lib/template-store.es6 index f7d37a050..ff08dd6da 100644 --- a/app/internal_packages/composer-templates/lib/template-store.es6 +++ b/app/internal_packages/composer-templates/lib/template-store.es6 @@ -297,7 +297,6 @@ class TemplateStore extends MailspringStore { templateBody + signature, session.draft().body ); - Actions.recordUserEvent('Email Template Inserted'); session.changes.add({ body: draftHtml }); } }); diff --git a/app/internal_packages/composer-translate/lib/main.jsx b/app/internal_packages/composer-translate/lib/main.jsx index 48610532c..ea449db34 100644 --- a/app/internal_packages/composer-translate/lib/main.jsx +++ b/app/internal_packages/composer-translate/lib/main.jsx @@ -66,10 +66,6 @@ class TranslateButton extends React.Component { const draftHtml = this.props.draft.body; const text = QuotedHTMLTransformer.removeQuotedHTML(draftHtml); - Actions.recordUserEvent('Email Translated', { - language: YandexLanguages[lang], - }); - const queryParams = new URLSearchParams(); queryParams.set('key', YandexTranslationKey); queryParams.set('lang', YandexLanguages[lang]); diff --git a/app/internal_packages/message-view-on-github/lib/view-on-github-button.jsx b/app/internal_packages/message-view-on-github/lib/view-on-github-button.jsx index 1c110baad..5d96e7379 100644 --- a/app/internal_packages/message-view-on-github/lib/view-on-github-button.jsx +++ b/app/internal_packages/message-view-on-github/lib/view-on-github-button.jsx @@ -1,5 +1,5 @@ import { shell } from 'electron'; -import { Actions, React, PropTypes } from 'mailspring-exports'; +import { React, PropTypes } from 'mailspring-exports'; import { RetinaImg, KeyCommandsRegion } from 'mailspring-component-kit'; import GithubStore from './github-store'; @@ -140,7 +140,6 @@ export default class ViewOnGithubButton extends React.Component { * request. */ _openLink = () => { - Actions.recordUserEvent('Github Thread Opened', { pageUrl: this.state.link }); if (this.state.link) { shell.openExternal(this.state.link); } diff --git a/app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx b/app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx index f9a2393ae..dcbaaccc9 100644 --- a/app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx +++ b/app/internal_packages/onboarding/lib/decorators/create-page-for-form.jsx @@ -1,6 +1,6 @@ import { shell } from 'electron'; import { RetinaImg } from 'mailspring-component-kit'; -import { Actions, React, ReactDOM, PropTypes } from 'mailspring-exports'; +import { React, ReactDOM, PropTypes } from 'mailspring-exports'; import OnboardingActions from '../onboarding-actions'; import { finalizeAndValidateAccount } from '../onboarding-helpers'; @@ -120,11 +120,6 @@ const CreatePageForForm = FormComponent => { OnboardingActions.finishAndAddAccount(validated); }) .catch(err => { - Actions.recordUserEvent('Email Account Auth Failed', { - errorMessage: err.message, - provider: account.provider, - }); - const errorFieldNames = []; if (err.message.includes('Authentication Error')) { diff --git a/app/internal_packages/onboarding/lib/oauth-signin-page.jsx b/app/internal_packages/onboarding/lib/oauth-signin-page.jsx index b4775bd35..fd63b4912 100644 --- a/app/internal_packages/onboarding/lib/oauth-signin-page.jsx +++ b/app/internal_packages/onboarding/lib/oauth-signin-page.jsx @@ -1,5 +1,5 @@ import { ipcRenderer, shell, clipboard } from 'electron'; -import { React, PropTypes, Actions } from 'mailspring-exports'; +import { React, PropTypes } from 'mailspring-exports'; import { RetinaImg } from 'mailspring-component-kit'; import FormErrorMessage from './form-error-message'; @@ -75,10 +75,6 @@ export default class OAuthSignInPage extends React.Component { _handleError(err) { this.setState({ authStage: 'error', errorMessage: err.message }); AppEnv.reportError(err); - Actions.recordUserEvent('Email Account Auth Failed', { - errorMessage: err.message, - provider: 'gmail', - }); } startPollingForResponse() { diff --git a/app/internal_packages/onboarding/lib/onboarding-store.es6 b/app/internal_packages/onboarding/lib/onboarding-store.es6 index 13c6fda95..48fb101c2 100644 --- a/app/internal_packages/onboarding/lib/onboarding-store.es6 +++ b/app/internal_packages/onboarding/lib/onboarding-store.es6 @@ -1,4 +1,4 @@ -import { AccountStore, Account, Actions, IdentityStore } from 'mailspring-exports'; +import { AccountStore, Account, IdentityStore } from 'mailspring-exports'; import { ipcRenderer } from 'electron'; import MailspringStore from 'mailspring-store'; @@ -136,15 +136,8 @@ class OnboardingStore extends MailspringStore { AppEnv.displayWindow(); - Actions.recordUserEvent('Email Account Auth Succeeded', { - provider: account.provider, - }); - if (isFirstAccount) { this._onMoveToPage('initial-preferences'); - Actions.recordUserEvent('First Account Linked', { - provider: account.provider, - }); } else { // let them see the "success" screen for a moment // before the window is closed. diff --git a/app/internal_packages/onboarding/lib/page-welcome.jsx b/app/internal_packages/onboarding/lib/page-welcome.jsx index cd05fc2d3..0fb1c4536 100644 --- a/app/internal_packages/onboarding/lib/page-welcome.jsx +++ b/app/internal_packages/onboarding/lib/page-welcome.jsx @@ -6,15 +6,6 @@ export default class WelcomePage extends React.Component { static displayName = 'WelcomePage'; _onContinue = () => { - // We don't have a NylasId yet and therefore can't track the "Welcome - // Page Finished" event. - // - // If a user already has a Nylas ID and gets to this page (which - // happens if they sign out of all of their accounts), then it would - // properly fire. This is a rare case though and we don't want - // analytics users thinking it's part of the full funnel. - // - // Actions.recordUserEvent('Welcome Page Finished'); OnboardingActions.moveToPage('tutorial'); }; diff --git a/app/internal_packages/send-later/lib/send-later-button.jsx b/app/internal_packages/send-later/lib/send-later-button.jsx index 893488a08..18d0fe4b7 100644 --- a/app/internal_packages/send-later/lib/send-later-button.jsx +++ b/app/internal_packages/send-later/lib/send-later-button.jsx @@ -75,12 +75,6 @@ class SendLaterButton extends Component { } this.setState({ saving: true }); - const sendInSec = Math.round((new Date(sendLaterDate).valueOf() - Date.now()) / 1000); - Actions.recordUserEvent('Draft Send Later', { - timeInSec: sendInSec, - timeInLog10Sec: Math.log10(sendInSec), - label: dateLabel, - }); } this.props.session.changes.addPluginMetadata(PLUGIN_ID, { diff --git a/app/internal_packages/send-reminders/lib/send-reminders-utils.es6 b/app/internal_packages/send-reminders/lib/send-reminders-utils.es6 index 7a08da4c6..4cf800504 100644 --- a/app/internal_packages/send-reminders/lib/send-reminders-utils.es6 +++ b/app/internal_packages/send-reminders/lib/send-reminders-utils.es6 @@ -30,13 +30,6 @@ async function incrementMetadataUse(model, expiration) { return false; } } - if (expiration) { - const seconds = Math.round((new Date(expiration).getTime() - Date.now()) / 1000); - Actions.recordUserEvent('Set Reminder', { - seconds: seconds, - secondsLog10: Math.log10(seconds), - }); - } return true; } diff --git a/app/internal_packages/thread-search/lib/search-query-subscription.es6 b/app/internal_packages/thread-search/lib/search-query-subscription.es6 index 7712d8549..70c02e472 100644 --- a/app/internal_packages/thread-search/lib/search-query-subscription.es6 +++ b/app/internal_packages/thread-search/lib/search-query-subscription.es6 @@ -1,6 +1,5 @@ import _ from 'underscore'; import { - Actions, Thread, DatabaseStore, SearchQueryParser, @@ -119,31 +118,8 @@ class SearchQuerySubscription extends MutableQuerySubscription { return; } - let timeToFirstServerResults = null; - let timeToFirstThreadSelected = null; - const timeInsideSearch = Math.round((Date.now() - this._searchStartedAt) / 1000); - const numItems = this._focusedThreadCount; - const didSelectAnyThreads = numItems > 0; + // Not Implemented - if (this._firstThreadSelectedAt) { - timeToFirstThreadSelected = Math.round( - (this._firstThreadSelectedAt - this._searchStartedAt) / 1000 - ); - } - if (this._resultsReceivedAt) { - timeToFirstServerResults = Math.round( - (this._resultsReceivedAt - this._searchStartedAt) / 1000 - ); - } - - const data = { - numItems, - timeInsideSearch, - didSelectAnyThreads, - timeToFirstServerResults, - timeToFirstThreadSelected, - }; - Actions.recordUserEvent('Search Performed', data); this.resetData(); } diff --git a/app/internal_packages/thread-snooze/lib/snooze-store.es6 b/app/internal_packages/thread-snooze/lib/snooze-store.es6 index eaafc2c4c..da8b9e133 100644 --- a/app/internal_packages/thread-snooze/lib/snooze-store.es6 +++ b/app/internal_packages/thread-snooze/lib/snooze-store.es6 @@ -29,20 +29,6 @@ class SnoozeStore extends MailspringStore { this.unsubscribers.forEach(unsub => unsub()); } - _recordSnoozeEvent(threads, snoozeDate, label) { - try { - const timeInSec = Math.round((new Date(snoozeDate).valueOf() - Date.now()) / 1000); - Actions.recordUserEvent('Threads Snoozed', { - timeInSec: timeInSec, - timeInLog10Sec: Math.log10(timeInSec), - label: label, - numItems: threads.length, - }); - } catch (e) { - // Do nothing - } - } - _onSnoozeThreads = async (threads, snoozeDate, label) => { try { // ensure the user is authorized to use this feature @@ -52,9 +38,6 @@ class SnoozeStore extends MailspringStore { iconUrl: 'mailspring://thread-snooze/assets/ic-snooze-modal@2x.png', }); - // log to analytics - this._recordSnoozeEvent(threads, snoozeDate, label); - // move the threads to the snoozed folder await moveThreads(threads, { snooze: true, diff --git a/app/internal_packages_disabled/analytics/analytics-electron/index.es6 b/app/internal_packages_disabled/analytics/analytics-electron/index.es6 deleted file mode 100644 index 1c210dd3e..000000000 --- a/app/internal_packages_disabled/analytics/analytics-electron/index.es6 +++ /dev/null @@ -1,291 +0,0 @@ -/* eslint no-param-reassign: 0 */ -const assert = require('assert'); -const crypto = require('crypto'); -const validate = require('@segment/loosely-validate-event'); -const debug = require('debug')('analytics-node'); -const version = `3.0.0`; - -// BG: Dependencies of analytics-node I lifted in - -// https://github.com/segmentio/crypto-token/blob/master/lib/index.js -const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - -function uid(length, fn) { - const str = bytes => { - const res = []; - for (let i = 0; i < bytes.length; i++) { - res.push(chars[bytes[i] % chars.length]); - } - return res.join(''); - }; - - if (typeof length === 'function') { - fn = length; - length = null; - } - if (!length) { - length = 10; - } - if (!fn) { - return str(crypto.randomBytes(length)); - } - - crypto.randomBytes(length, (err, bytes) => { - if (err) { - fn(err); - return; - } - fn(null, str(bytes)); - }); - return null; -} - -// https://github.com/stephenmathieson/remove-trailing-slash/blob/master/index.js -function removeSlash(str) { - return String(str).replace(/\/+$/, ''); -} - -const setImmediate = global.setImmediate || process.nextTick.bind(process); -const noop = () => {}; - -export default class Analytics { - /** - * Initialize a new `Analytics` with your Segment project's `writeKey` and an - * optional dictionary of `options`. - * - * @param {String} writeKey - * @param {Object} [options] (optional) - * @property {Number} flushAt (default: 20) - * @property {Number} flushInterval (default: 10000) - * @property {String} host (default: 'https://api.segment.io') - */ - - constructor(writeKey, options) { - options = options || {}; - - assert(writeKey, "You must pass your Segment project's write key."); - - this.queue = []; - this.writeKey = writeKey; - this.host = removeSlash(options.host || 'https://api.segment.io'); - this.flushAt = Math.max(options.flushAt, 1) || 20; - this.flushInterval = options.flushInterval || 10000; - this.flushed = false; - } - - /** - * Send an identify `message`. - * - * @param {Object} message - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - identify(message, callback) { - validate(message, 'identify'); - this.enqueue('identify', message, callback); - return this; - } - - /** - * Send a group `message`. - * - * @param {Object} message - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - group(message, callback) { - validate(message, 'group'); - this.enqueue('group', message, callback); - return this; - } - - /** - * Send a track `message`. - * - * @param {Object} message - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - track(message, callback) { - validate(message, 'track'); - this.enqueue('track', message, callback); - return this; - } - - /** - * Send a page `message`. - * - * @param {Object} message - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - page(message, callback) { - validate(message, 'page'); - this.enqueue('page', message, callback); - return this; - } - - /** - * Send a screen `message`. - * - * @param {Object} message - * @param {Function} fn (optional) - * @return {Analytics} - */ - - screen(message, callback) { - validate(message, 'screen'); - this.enqueue('screen', message, callback); - return this; - } - - /** - * Send an alias `message`. - * - * @param {Object} message - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - alias(message, callback) { - validate(message, 'alias'); - this.enqueue('alias', message, callback); - return this; - } - - /** - * Add a `message` of type `type` to the queue and - * check whether it should be flushed. - * - * @param {String} type - * @param {Object} message - * @param {Functino} [callback] (optional) - * @api private - */ - - enqueue(type, message, callback) { - callback = callback || noop; - - message = Object.assign({}, message); - message.type = type; - message.context = Object.assign( - { - library: { - name: 'analytics-node', - version, - }, - }, - message.context - ); - - message._metadata = Object.assign( - { - nodeVersion: process.versions.node, - }, - message._metadata - ); - - if (!message.timestamp) { - message.timestamp = new Date(); - } - - if (!message.messageId) { - message.messageId = `node-${uid(32)}`; - } - - debug('%s: %o', type, message); - - this.queue.push({ message, callback }); - - if (!this.flushed) { - this.flushed = true; - this.flush(); - return; - } - - if (this.queue.length >= this.flushAt) { - this.flush(); - } - - if (this.flushInterval && !this.timer) { - this.timer = setTimeout(this.flush.bind(this), this.flushInterval); - } - } - - /** - * Flush the current queue - * - * @param {Function} [callback] (optional) - * @return {Analytics} - */ - - async flush(callback) { - callback = callback || noop; - - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - - if (!this.queue.length) { - setImmediate(callback); - return; - } - - const items = this.queue.splice(0, this.flushAt); - const callbacks = items.map(item => item.callback); - const messages = items.map(item => item.message); - - const data = { - batch: messages, - timestamp: new Date(), - sentAt: new Date(), - }; - - debug('flush: %o', data); - - const options = { - body: JSON.stringify(data), - credentials: 'include', - headers: new Headers(), - method: 'POST', - }; - options.headers.set('Accept', 'application/json'); - options.headers.set('Authorization', `Basic ${btoa(`${this.writeKey}:`)}`); - options.headers.set('Content-Type', 'application/json'); - - const runCallbacks = err => { - callbacks.forEach(cb => cb(err)); - callback(err, data); - debug('flushed: %o', data); - }; - - let resp = null; - try { - resp = await fetch(`${this.host}/v1/batch`, options); - } catch (err) { - runCallbacks(err, null); - return; - } - - if (!resp.ok) { - runCallbacks(new Error(`${resp.statusCode}: ${resp.statusText}`), null); - return; - } - - const body = await resp.json(); - if (body.error) { - runCallbacks(new Error(body.error.message), null); - return; - } - runCallbacks(null, { - status: resp.statusCode, - body: body, - ok: true, - }); - } -} diff --git a/app/internal_packages_disabled/analytics/analytics-electron/what-is-this.md b/app/internal_packages_disabled/analytics/analytics-electron/what-is-this.md deleted file mode 100644 index 11ec2eeaa..000000000 --- a/app/internal_packages_disabled/analytics/analytics-electron/what-is-this.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains a modified version of analytics-node. The original version uses `superagent`, which is both unnecessary (since we have both Browser and Node APIs and can use `fetch` and also added ~2.1MB of JavaScript to Mailspring.) \ No newline at end of file diff --git a/app/internal_packages_disabled/analytics/lib/analytics-store.es6 b/app/internal_packages_disabled/analytics/lib/analytics-store.es6 deleted file mode 100644 index 8fd9c0de9..000000000 --- a/app/internal_packages_disabled/analytics/lib/analytics-store.es6 +++ /dev/null @@ -1,154 +0,0 @@ -import _ from 'underscore'; -import MailspringStore from 'mailspring-store'; -import { - IdentityStore, - Actions, - AccountStore, - FocusedPerspectiveStore, - MailspringAPIRequest, -} from 'mailspring-exports'; - -import AnalyticsSink from '../analytics-electron'; - -/** - * We wait 15 seconds to give the alias time to register before we send - * any events. - */ -const DEBOUNCE_TIME = 5 * 1000; - -class AnalyticsStore extends MailspringStore { - activate() { - // Allow requests to be grouped together if they're fired back-to-back, - // but generally report each event as it happens. This segment library - // is intended for a server where the user doesn't quit... - this.analytics = new AnalyticsSink('mailspring', { - host: `${MailspringAPIRequest.rootURLForServer('identity')}/api/s`, - flushInterval: 500, - flushAt: 5, - }); - this.launchTime = Date.now(); - - const identifySoon = _.debounce(this.identify, DEBOUNCE_TIME); - identifySoon(); - - // also ping the server every hour to make sure someone running - // the app for days has up-to-date traits. - setInterval(identifySoon, 60 * 60 * 1000); // 60 min - - this.listenTo(IdentityStore, identifySoon); - this.listenTo(Actions.recordUserEvent, (eventName, eventArgs) => { - this.track(eventName, eventArgs); - }); - } - - // Properties applied to all events (only). - eventState() { - // Get a bit of context about the current perspective - // so we can assess usage of unified inbox, etc. - const perspective = FocusedPerspectiveStore.current(); - let currentProvider = null; - - if (perspective && perspective.accountIds.length > 1) { - currentProvider = 'Unified'; - } else { - // Warning: when you auth a new account there's a single moment where the account cannot be found - const account = perspective - ? AccountStore.accountForId(perspective.accountIds[0]) - : AccountStore.accounts()[0]; - currentProvider = account && account.displayProvider(); - } - - return { - currentProvider, - }; - } - - // Properties applied to all events and all people during an identify. - superTraits() { - const theme = AppEnv.themes ? AppEnv.themes.getActiveTheme() : null; - - return { - version: AppEnv.getVersion().split('-')[0], - platform: process.platform, - activeTheme: theme ? theme.name : null, - workspaceMode: AppEnv.config.get('core.workspace.mode'), - }; - } - - baseTraits() { - return Object.assign({}, this.superTraits(), { - firstDaySeen: this.firstDaySeen(), - timeSinceLaunch: (Date.now() - this.launchTime) / 1000, - accountCount: AccountStore.accounts().length, - providers: AccountStore.accounts().map(a => a.displayProvider()), - }); - } - - personalTraits() { - const identity = IdentityStore.identity(); - if (!(identity && identity.id)) { - return {}; - } - - return { - email: identity.emailAddress, - firstName: identity.firstName, - lastName: identity.lastName, - }; - } - - track(eventName, eventArgs = {}) { - // if (AppEnv.inDevMode()) { return } - - const identity = IdentityStore.identity(); - if (!(identity && identity.id)) { - return; - } - - this.analytics.track({ - event: eventName, - userId: identity.id, - properties: Object.assign({}, eventArgs, this.eventState(), this.superTraits()), - }); - } - - firstDaySeen() { - let firstDaySeen = AppEnv.config.get('firstDaySeen'); - if (!firstDaySeen) { - const [y, m, d] = new Date().toISOString().split(/[-|T]/); - firstDaySeen = `${m}/${d}/${y}`; - AppEnv.config.set('firstDaySeen', firstDaySeen); - } - return firstDaySeen; - } - - identify = () => { - if (!AppEnv.isMainWindow()) { - return; - } - - const identity = IdentityStore.identity(); - if (!(identity && identity.id)) { - return; - } - - this.analytics.identify({ - userId: identity.id, - traits: this.baseTraits(), - integrations: { All: true }, - }); - - // Ensure we never send PI anywhere but Mixpanel - - this.analytics.identify({ - userId: identity.id, - traits: Object.assign({}, this.baseTraits(), this.personalTraits()), - integrations: { - All: false, - Mixpanel: true, - }, - }); - }; -} - -export default new AnalyticsStore(); diff --git a/app/internal_packages_disabled/analytics/lib/main.es6 b/app/internal_packages_disabled/analytics/lib/main.es6 deleted file mode 100644 index fa31d329e..000000000 --- a/app/internal_packages_disabled/analytics/lib/main.es6 +++ /dev/null @@ -1,5 +0,0 @@ -import AnalyticsStore from './analytics-store'; - -export function activate() { - AnalyticsStore.activate(); -} diff --git a/app/internal_packages_disabled/analytics/package.json b/app/internal_packages_disabled/analytics/package.json deleted file mode 100644 index 3ec1462e2..000000000 --- a/app/internal_packages_disabled/analytics/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "analytics", - "version": "0.1.0", - "main": "./lib/main", - "description": "Analytics", - "license": "Proprietary", - "private": true, - "windowTypes": { - "default": true - }, - "engines": { - "mailspring": "*" - } -} diff --git a/app/internal_packages_disabled/thread-sharing/lib/thread-sharing-popover.jsx b/app/internal_packages_disabled/thread-sharing/lib/thread-sharing-popover.jsx index 49216e94a..3e4b20dc1 100644 --- a/app/internal_packages_disabled/thread-sharing/lib/thread-sharing-popover.jsx +++ b/app/internal_packages_disabled/thread-sharing/lib/thread-sharing-popover.jsx @@ -54,7 +54,7 @@ export default class ThreadSharingPopover extends React.Component { } _onToggleShared = async () => { - const { thread, accountId } = this.props; + const { thread } = this.props; const { shared } = this.state; this.setState({ saving: true }); @@ -64,9 +64,6 @@ export default class ThreadSharingPopover extends React.Component { return; } - if (!shared === true) { - Actions.recordUserEvent('Thread Sharing Enabled', { accountId, threadId: thread.id }); - } Actions.queueTask( SyncbackMetadataTask.forSaving({ model: thread, diff --git a/app/spec/action-bridge-spec.coffee b/app/spec/action-bridge-spec.coffee index 1dfe6d19a..a960ba9cc 100644 --- a/app/spec/action-bridge-spec.coffee +++ b/app/spec/action-bridge-spec.coffee @@ -27,7 +27,7 @@ describe "ActionBridge", -> it "should not rebroadcast mainWindow actions since it is the main window", -> spyOn(@bridge, 'onRebroadcast') - testAction = Actions.recordUserEvent + testAction = Actions.queueTask testAction('bla') expect(@bridge.onRebroadcast).not.toHaveBeenCalled() @@ -57,7 +57,7 @@ describe "ActionBridge", -> it "should rebroadcast mainWindow actions", -> spyOn(@bridge, 'onRebroadcast') - testAction = Actions.recordUserEvent + testAction = Actions.queueTask testAction('bla') expect(@bridge.onRebroadcast).toHaveBeenCalled() diff --git a/app/src/components/metadata-composer-toggle-button.jsx b/app/src/components/metadata-composer-toggle-button.jsx index a27a487a5..547d02c63 100644 --- a/app/src/components/metadata-composer-toggle-button.jsx +++ b/app/src/components/metadata-composer-toggle-button.jsx @@ -1,7 +1,6 @@ import { React, PropTypes, - Actions, MailspringAPIRequest, APIError, FeatureUsageStore, @@ -87,10 +86,8 @@ export default class MetadataComposerToggleButton extends React.Component { } _onClick = async () => { - const { pluginName, pluginId } = this.props; + const { pluginId } = this.props; let nextEnabled = !this._isEnabled(); - const dir = nextEnabled ? 'Enabled' : 'Disabled'; - if (this.state.pending) { return; } @@ -114,7 +111,6 @@ export default class MetadataComposerToggleButton extends React.Component { } } - Actions.recordUserEvent(`${pluginName} ${dir}`); AppEnv.config.set(this._configKey(), nextEnabled); this._setEnabled(nextEnabled); }; diff --git a/app/src/flux/actions.es6 b/app/src/flux/actions.es6 index 3e7abd208..9d0914a4d 100644 --- a/app/src/flux/actions.es6 +++ b/app/src/flux/actions.es6 @@ -468,11 +468,6 @@ class Actions { */ static pushSheet = ActionScopeWindow; - /* - Public: Publish a user event to any analytics services linked to N1. - */ - static recordUserEvent = ActionScopeMainWindow; - static addMailRule = ActionScopeWindow; static reorderMailRule = ActionScopeWindow; static updateMailRule = ActionScopeWindow; diff --git a/app/src/flux/stores/draft-store.es6 b/app/src/flux/stores/draft-store.es6 index 09470a087..700b93493 100644 --- a/app/src/flux/stores/draft-store.es6 +++ b/app/src/flux/stores/draft-store.es6 @@ -182,7 +182,6 @@ class DraftStore extends MailspringStore { }; _onComposeReply = ({ thread, threadId, message, messageId, popout, type, behavior }) => { - Actions.recordUserEvent('Draft Created', { type }); return Promise.props(this._modelifyContext({ thread, threadId, message, messageId })) .then(({ message: m, thread: t }) => { return DraftFactory.createOrUpdateDraftForReply({ message: m, thread: t, type, behavior }); @@ -193,7 +192,6 @@ class DraftStore extends MailspringStore { }; _onComposeForward = async ({ thread, threadId, message, messageId, popout }) => { - Actions.recordUserEvent('Draft Created', { type: 'forward' }); return Promise.props(this._modelifyContext({ thread, threadId, message, messageId })) .then(({ thread: t, message: m }) => { return DraftFactory.createDraftForForward({ thread: t, message: m }); @@ -275,7 +273,6 @@ class DraftStore extends MailspringStore { }; _onPopoutBlankDraft = async () => { - Actions.recordUserEvent('Draft Created', { type: 'new' }); const draft = await DraftFactory.createDraft(); const { headerMessageId } = await this._finalizeAndPersistNewMessage(draft); await this._onPopoutDraft(headerMessageId, { newDraft: true }); diff --git a/app/src/flux/stores/workspace-store.coffee b/app/src/flux/stores/workspace-store.coffee index 94147587b..d22c8ff14 100644 --- a/app/src/flux/stores/workspace-store.coffee +++ b/app/src/flux/stores/workspace-store.coffee @@ -103,12 +103,8 @@ class WorkspaceStore extends MailspringStore throw new Error("Actions.toggleWorkspaceLocationHidden - pass a WorkspaceStore.Location") if @_hiddenLocations[location.id] - if location is @Location.MessageListSidebar - Actions.recordUserEvent("Sidebar Opened") delete @_hiddenLocations[location.id] else - if location is @Location.MessageListSidebar - Actions.recordUserEvent("Sidebar Closed") @_hiddenLocations[location.id] = location AppEnv.config.set('core.workspace.hiddenLocations', @_hiddenLocations) diff --git a/app/src/flux/tasks/change-starred-task.es6 b/app/src/flux/tasks/change-starred-task.es6 index 8c830ca83..8b8213411 100644 --- a/app/src/flux/tasks/change-starred-task.es6 +++ b/app/src/flux/tasks/change-starred-task.es6 @@ -44,17 +44,4 @@ export default class ChangeStarredTask extends ChangeMailTask { task.starred = !this.starred; return task; } - - recordUserEvent() { - if (this.source === 'Mail Rules') { - return; - } - const eventName = this.starred ? 'Starred' : 'Unstarred'; - Actions.recordUserEvent(`Threads ${eventName}`, { - source: this.source, - numThreads: this.threadIds.length, - description: this.description(), - isUndo: this.isUndo, - }); - } } diff --git a/app/src/flux/tasks/send-draft-task.es6 b/app/src/flux/tasks/send-draft-task.es6 index 326ea9da9..f13140d4a 100644 --- a/app/src/flux/tasks/send-draft-task.es6 +++ b/app/src/flux/tasks/send-draft-task.es6 @@ -86,7 +86,6 @@ export default class SendDraftTask extends Task { } onSuccess() { - Actions.recordUserEvent('Draft Sent'); Actions.draftDeliverySucceeded({ headerMessageId: this.draft.headerMessageId, accountId: this.draft.accountId, @@ -143,9 +142,6 @@ export default class SendDraftTask extends Task { errorMessage, errorDetail, }); - Actions.recordUserEvent('Draft Sending Errored', { - key: key, - }); } // note - this code must match what is used for send-later! diff --git a/app/src/global/mailspring-exports.es6 b/app/src/global/mailspring-exports.es6 index 0a1f9cfcb..e55ce888f 100644 --- a/app/src/global/mailspring-exports.es6 +++ b/app/src/global/mailspring-exports.es6 @@ -191,7 +191,6 @@ lazyLoad(`SanitizeTransformer`, 'services/sanitize-transformer'); lazyLoad(`QuotedHTMLTransformer`, 'services/quoted-html-transformer'); lazyLoad(`InlineStyleTransformer`, 'services/inline-style-transformer'); lazyLoad(`SearchableComponentMaker`, 'searchable-components/searchable-component-maker'); -lazyLoad(`BatteryStatusManager`, 'services/battery-status-manager'); // Errors lazyLoadWithGetter(`APIError`, () => require('../flux/errors').APIError); diff --git a/app/src/services/battery-status-manager.es6 b/app/src/services/battery-status-manager.es6 deleted file mode 100644 index 3de1744f8..000000000 --- a/app/src/services/battery-status-manager.es6 +++ /dev/null @@ -1,53 +0,0 @@ -import moment from 'moment-timezone'; -import Actions from '../flux/actions'; - -class BatteryStatusManager { - constructor() { - this._callbacks = []; - this._battery = null; - this._lastChangeTime = Date.now(); - this.activate(); - } - - async activate() { - if (this._battery) { - return; - } - this._battery = await navigator.getBattery(); - this._battery.addEventListener('chargingchange', this._onChargingChange); - } - - deactivate() { - if (!this._battery) { - return; - } - this._battery.removeEventListener('chargingchange', this._onChargingChange); - this._battery = null; - } - - _onChargingChange = () => { - const changeTime = Date.now(); - Actions.recordUserEvent('Battery State Changed', { - oldState: this.isBatteryCharging() ? 'battery' : 'ac', - oldStateDuration: Math.min( - changeTime - this._lastChangeTime, - moment.duration(12, 'hours').asMilliseconds() - ), - }); - this._lastChangeTime = changeTime; - this._callbacks.forEach(cb => cb()); - }; - - onChange(callback) { - this._callbacks.push(callback); - } - - isBatteryCharging() { - if (!this._battery) { - return false; - } - return this._battery.charging; - } -} - -export default new BatteryStatusManager();