diff --git a/package-lock.json b/package-lock.json index 7f2ca7edac..553d7ca5cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3083,6 +3083,795 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "optional": true, + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -7534,6 +8323,7 @@ "anymatch": "2.0.0", "exec-sh": "0.2.1", "fb-watchman": "2.0.0", + "fsevents": "1.1.3", "micromatch": "3.1.10", "minimist": "1.2.0", "walker": "1.0.7", diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index f575dc1017..8d315d3f0e 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -6,10 +6,6 @@ (def ethereum-rpc-url "http://localhost:8545") -(def server-address "http://api.status.im/") -;; (def server-address "http://10.0.3.2:3000/") -;; (def server-address "http://localhost:3000/") - (def text-content-type "text/plain") (def content-type-log-message "log-message") (def content-type-command "command") diff --git a/src/status_im/ui/screens/accounts/login/events.cljs b/src/status_im/ui/screens/accounts/login/events.cljs index 6c5250350a..395a71b084 100644 --- a/src/status_im/ui/screens/accounts/login/events.cljs +++ b/src/status_im/ui/screens/accounts/login/events.cljs @@ -127,7 +127,6 @@ (assoc-in [:accounts/create :step] :enter-name)) :dispatch-n (concat [[:stop-debugging] - (when (:sharing-usage-data? (accounts address)) [:register-mixpanel-tracking address]) [:initialize-account address (when (not= view-id :create-account) [[:navigate-to-clean :home]])]])} diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index b027764749..3a28ff9699 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -28,7 +28,7 @@ [re-frame.core :as re-frame] [status-im.native-module.core :as status] [status-im.ui.components.permissions :as permissions] - [status-im.constants :refer [console-chat-id]] + [status-im.constants :as constants] [status-im.data-store.core :as data-store] [status-im.i18n :as i18n] [status-im.js-dependencies :as dependencies] @@ -108,14 +108,6 @@ (doseq [opts opts-seq] (call-jail-function opts)))) -(re-frame/reg-fx - :http-post - (fn [{:keys [action data success-event-creator failure-event-creator timeout-ms]}] - (let [on-success #(re-frame/dispatch (success-event-creator %)) - on-error #(re-frame/dispatch (failure-event-creator %)) - opts {:timeout-ms timeout-ms}] - (http/post action data on-success on-error opts)))) - (defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}] (let [on-success #(re-frame/dispatch (success-event-creator %)) on-error #(re-frame/dispatch (failure-event-creator %)) @@ -256,7 +248,7 @@ inbox/wnode] :or [network (get app-db :network) wnode (get app-db :inbox/wnode)]} [_ address]] - (let [console-contact (get contacts console-chat-id)] + (let [console-contact (get contacts constants/console-chat-id)] (cond-> (assoc app-db :access-scope->commands-responses access-scope->commands-responses :accounts/current-account-id address @@ -275,7 +267,7 @@ :network network :inbox/wnode wnode) console-contact - (assoc :contacts/contacts {console-chat-id console-contact}))))) + (assoc :contacts/contacts {constants/console-chat-id console-contact}))))) (handlers/register-handler-fx :initialize-account @@ -330,25 +322,6 @@ (fn [_ _] {::get-fcm-token-fx nil})) -(defn- track [id event] - (let [anonid (ethereum/sha3 id)] - (doseq [{:keys [label properties]} (mixpanel/matching-events event mixpanel/event-by-trigger)] - (mixpanel/track anonid label properties)))) - -(def hook-id :mixpanel-callback) - -(handlers/register-handler-fx - :register-mixpanel-tracking - (fn [_ [_ id]] - (re-frame/add-post-event-callback hook-id #(track id %)) - nil)) - -(handlers/register-handler-fx - :unregister-mixpanel-tracking - (fn [] - (re-frame/remove-post-event-callback hook-id) - nil)) - ;; Because we send command to jail in params and command `:ref` is a lookup vector with ;; keyword in it (for example `["transactor" :command 51 "send"]`), we lose that keyword ;; information in the process of converting to/from JSON, and we need to restore it diff --git a/src/status_im/ui/screens/usage_data/events.cljs b/src/status_im/ui/screens/usage_data/events.cljs index 06e3b9b305..e73d47d29e 100644 --- a/src/status_im/ui/screens/usage_data/events.cljs +++ b/src/status_im/ui/screens/usage_data/events.cljs @@ -4,12 +4,6 @@ (handlers/register-handler-fx :help-improve-handler - (fn [{{:accounts/keys [accounts current-account-id] :as db} :db} [_ yes? address next]] - (let [{:keys [sharing-usage-data?]} (get accounts current-account-id)] - (merge (accounts/account-update {:sharing-usage-data? yes?} {:db db}) - {:dispatch-n [(if yes? - [:register-mixpanel-tracking address] - (when (and next sharing-usage-data?) - [:unregister-mixpanel-tracking])) - (or next [:navigate-to-clean :home])]})))) - + (fn [{db :db} [_ yes? next]] + (merge (accounts/account-update {:sharing-usage-data? yes?} {:db db}) + {:dispatch (or next [:navigate-to-clean :home])}))) diff --git a/src/status_im/ui/screens/usage_data/views.cljs b/src/status_im/ui/screens/usage_data/views.cljs index 2c9e044df5..38fe0d2eb2 100644 --- a/src/status_im/ui/screens/usage_data/views.cljs +++ b/src/status_im/ui/screens/usage_data/views.cljs @@ -9,8 +9,7 @@ [status-im.ui.screens.usage-data.styles :as styles])) (views/defview usage-data [] - (views/letsubs [next [:get-screen-params] - account [:get-current-account]] + (views/letsubs [next [:get-screen-params]] [react/view {:style styles/usage-data-view} [status-bar/status-bar {:flat? true}] [react/view {:style styles/logo-container} @@ -24,9 +23,9 @@ (i18n/label :t/help-improve-description)]] [react/view styles/buttons-container [components.common/button {:style {:flex-direction :row} - :on-press #(re-frame/dispatch [:help-improve-handler true (:address account) next]) + :on-press #(re-frame/dispatch [:help-improve-handler true next]) :label (i18n/label :t/share-usage-data)}] [react/view styles/bottom-button-container - [components.common/button {:on-press #(re-frame/dispatch [:help-improve-handler false (:address account) next]) + [components.common/button {:on-press #(re-frame/dispatch [:help-improve-handler false next]) :label (i18n/label :t/dont-want-to-share) :background? false}]]]])) diff --git a/src/status_im/utils/handlers.cljs b/src/status_im/utils/handlers.cljs index 230279aefd..2e12098d08 100644 --- a/src/status_im/utils/handlers.cljs +++ b/src/status_im/utils/handlers.cljs @@ -3,6 +3,8 @@ [clojure.string :as string] [re-frame.core :refer [reg-event-db reg-event-fx] :as re-frame] [re-frame.interceptor :refer [->interceptor get-coeffect get-effect]] + [status-im.utils.ethereum.core :as ethereum] + [status-im.utils.mixpanel :as mixpanel] [taoensso.timbre :as log]) (:require-macros status-im.utils.handlers)) @@ -81,6 +83,26 @@ (throw (ex-info (check-spec-msg event-id new-db) {}))) context)))) +(def track-mixpanel + "send an event to mixpanel for tracking" + (->interceptor + :id track-mixpanel + :after + (fn track-handler + [context] + (let [new-db (get-coeffect context :db) + current-account-id (:accounts/current-account-id new-db)] + (when (get-in new-db [:accounts/accounts + current-account-id + :sharing-usage-data?]) + (let [event (get-coeffect context :event) + offline? (or (= :offline (:network-status new-db)) + (= :offline (:sync-state new-db))) + anon-id (ethereum/sha3 current-account-id)] + (doseq [{:keys [label properties]} + (mixpanel/matching-events event mixpanel/event-by-trigger)] + (mixpanel/track anon-id label properties offline?))))) + context))) (defn register-handler ([name handler] (register-handler name nil handler)) @@ -88,7 +110,10 @@ (reg-event-db name [debug-handlers-names (when js/goog.DEBUG check-spec) middleware] handler))) (def default-interceptors - [debug-handlers-names (when js/goog.DEBUG check-spec) (re-frame/inject-cofx :now)]) + [debug-handlers-names + (when js/goog.DEBUG check-spec) + (re-frame/inject-cofx :now) + track-mixpanel]) (defn register-handler-db ([name handler] (register-handler-db name nil handler)) diff --git a/src/status_im/utils/http.cljs b/src/status_im/utils/http.cljs index 96a42ed6d1..bb5d1b347a 100644 --- a/src/status_im/utils/http.cljs +++ b/src/status_im/utils/http.cljs @@ -9,23 +9,20 @@ (defn post "Performs an HTTP POST request" - ([action data on-success] - (post action data on-success nil)) - ([action data on-success on-error] - (post action data on-success on-error nil)) - ([action data on-success on-error {:keys [timeout-ms]}] - (-> (rn-dependencies/fetch (str const/server-address action) - (clj->js {:method "POST" - :headers {:accept "application/json" - :content-type "application/json"} - :body (.stringify js/JSON (clj->js data)) - :timeout (or timeout-ms http-request-default-timeout-ms)})) + ([url data on-success] + (post url data on-success nil)) + ([url data on-success on-error] + (post url data on-success on-error nil)) + ([url data on-success on-error {:keys [timeout-ms headers]}] + (-> (rn-dependencies/fetch + url + (clj->js (merge {:method "POST" + :body data + :timeout (or timeout-ms http-request-default-timeout-ms)} + (when headers + {:headers headers})))) (.then (fn [response] - (.text response))) - (.then (fn [text] - (let [json (.parse js/JSON text) - obj (js->clj json :keywordize-keys true)] - (on-success obj)))) + (on-success response))) (.catch (or on-error (fn [error] (utils/show-popup "Error" (str error)))))))) diff --git a/src/status_im/utils/mixpanel.cljs b/src/status_im/utils/mixpanel.cljs index e14e7f01a8..5d68ed9c12 100644 --- a/src/status_im/utils/mixpanel.cljs +++ b/src/status_im/utils/mixpanel.cljs @@ -1,13 +1,15 @@ (ns status-im.utils.mixpanel (:require-macros [status-im.utils.slurp :as slurp]) - (:require [cljs.reader :as reader] + (:require [cljs.core.async :as async] + [cljs.reader :as reader] [goog.crypt.base64 :as b64] [status-im.utils.build :as build] [status-im.utils.config :as config] [status-im.utils.datetime :as datetime] [status-im.utils.http :as http] [status-im.utils.platform :as platform] - [status-im.utils.types :as types])) + [status-im.utils.types :as types] + [taoensso.timbre :as log])) (def base-url "http://api.mixpanel.com/") (def base-track-url (str base-url "track/")) @@ -15,24 +17,65 @@ (defn encode [m] (b64/encodeString (types/clj->json m))) -(defn- build-url [id label props] - (str base-track-url - "?data=" - (encode {:event label - :properties (merge - {:token config/mixpanel-token - :distinct_id id - :os platform/os - :os-version platform/version - :app-version build/version - :time (datetime/timestamp)} - props)}))) +(defn- make-event [id label props] + {:event label + :properties (merge + {:token config/mixpanel-token + :distinct_id id + :os platform/os + :os-version platform/version + :app-version build/version + :time (datetime/timestamp)} + props)}) -(defn track [id label props] - (http/get (build-url id label props) nil identity)) +;; holds events that are accumulated while offline. will start throwing away old +;; events if we accumulate more than 2000 +(def ^:private pending-events-queue (async/chan (async/sliding-buffer 2000))) + +(defn- submit-batch + "Submit a batch of events to mixpanel via POST" + [events] + (let [done-chan (async/chan)] + (log/debug "submitting" (count events) "events") + (http/post base-track-url + (str "data=" (encode (into [] events))) + (fn [_] + (log/debug "successfully submitted events") + (async/go (async/close! done-chan))) + (fn [error] + (log/error "error while submitting events" error) + (async/go (async/close! done-chan)))) + done-chan)) + +;; maximum number of events that should be submitted to mixpanel's batch +;; endpoint at once (see https://mixpanel.com/help/reference/http) +(def max-batch-size 50) + +(defn drain-events-queue! + "Drains accumulated events and submits them in batches of " + ([] + (drain-events-queue! pending-events-queue submit-batch)) + ([queue callback] + (let [events (loop [accumulator []] + (if-let [event (async/poll! queue)] + (recur (conj accumulator event)) + accumulator))] + (async/go + (doseq [batch (partition-all max-batch-size events)] + (async/! pending-events-queue event)) + ;; drain queue if we are online + (when-not offline? + (async/go (async/