[ISSUE #3537] Added mixpanel support
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
parent
581d4f04a5
commit
f1e41cc7ab
1
.env
1
.env
|
@ -13,3 +13,4 @@ RN_BRIDGE_THRESHOLD_WARNINGS=0
|
|||
COMPILE_VIEWS_ENABLED=0
|
||||
POW_TARGET=0.001
|
||||
POW_TIME=1
|
||||
MIXPANEL_TOKEN=3f2e1a8970f159aa2a3d5dc5d65eab38
|
||||
|
|
|
@ -11,5 +11,6 @@ QUEUE_MESSAGE_ENABLED=1
|
|||
MANY_WHISPER_TOPICS_ENABLED=0
|
||||
RN_BRIDGE_THRESHOLD_WARNINGS=0
|
||||
COMPILE_VIEWS_ENABLED=0
|
||||
MIXPANEL_TOKEN=3f2e1a8970f159aa2a3d5dc5d65eab38
|
||||
POW_TARGET=0.001
|
||||
POW_TIME=1
|
||||
|
|
|
@ -11,5 +11,6 @@ QUEUE_MESSAGE_ENABLED=0
|
|||
MANY_WHISPER_TOPICS_ENABLED=0
|
||||
RN_BRIDGE_THRESHOLD_WARNINGS=0
|
||||
COMPILE_VIEWS_ENABLED=0
|
||||
MIXPANEL_TOKEN=2584e00100d319d12e538cc4d0fa9fc1
|
||||
POW_TARGET=0.2
|
||||
POW_TIME=1
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
(defn- generate-context
|
||||
"Generates context for jail call"
|
||||
[current-account-id chat-id to group-id]
|
||||
(merge {:platform platform/platform
|
||||
(merge {:platform platform/os
|
||||
:from current-account-id
|
||||
:to to
|
||||
:chat {:chat-id chat-id
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
::account-created
|
||||
[re-frame/trim-v (re-frame/inject-cofx :get-new-keypair!)
|
||||
(re-frame/inject-cofx ::get-signing-phrase) (re-frame/inject-cofx ::get-status)]
|
||||
(fn [{:keys [keypair signing-phrase status db] :as cofx} [{:keys [pubkey address mnemonic]} password]]
|
||||
(fn [{:keys [keypair signing-phrase status db]} [{:keys [pubkey address mnemonic]} password]]
|
||||
(let [normalized-address (utils.hex/normalize-hex address)
|
||||
account {:public-key pubkey
|
||||
:address normalized-address
|
||||
|
@ -208,6 +208,12 @@
|
|||
:dispatch [:navigate-to-clean :usage-data]}
|
||||
(account-update {:name (:name create)}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:account-finalized
|
||||
(fn [{db :db} _]
|
||||
{:db db
|
||||
:dispatch [:navigate-to-clean :home]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:update-sign-in-time
|
||||
(fn [{db :db now :now} _]
|
||||
|
@ -221,4 +227,4 @@
|
|||
(handlers/register-handler-fx
|
||||
:switch-dev-mode
|
||||
(fn [{db :db} [_ dev-mode]]
|
||||
(account-update {:db db} {:dev-mode? dev-mode})))
|
||||
(account-update {:db db} {:dev-mode? dev-mode})))
|
||||
|
|
|
@ -120,13 +120,14 @@
|
|||
|
||||
(register-handler-fx
|
||||
:change-account-handler
|
||||
(fn [{{:keys [view-id] :as db} :db} [_ error address]]
|
||||
(fn [{{:keys [accounts/accounts view-id] :as db} :db} [_ error address]]
|
||||
(if (nil? error)
|
||||
{:db (cond-> (dissoc db :accounts/login)
|
||||
(= view-id :create-account)
|
||||
(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]])]])}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
[clojure.string :as s]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.utils.contacts :as utils.contacts]
|
||||
[status-im.utils.utils :refer [http-post]]
|
||||
[status-im.utils.random :as random]
|
||||
[taoensso.timbre :as log]
|
||||
[cljs.reader :refer [read-string]]
|
||||
|
|
|
@ -34,12 +34,15 @@
|
|||
[status-im.js-dependencies :as dependencies]
|
||||
[status-im.ui.screens.db :refer [app-db]]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.crypt :as crypt]
|
||||
[status-im.utils.notifications :as notifications]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.instabug :as inst]
|
||||
[status-im.utils.mixpanel :as mixpanel]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
|
@ -113,14 +116,14 @@
|
|||
(let [on-success #(re-frame/dispatch (success-event-creator %))
|
||||
on-error #(re-frame/dispatch (failure-event-creator %))
|
||||
opts {:timeout-ms timeout-ms}]
|
||||
(utils/http-post action data on-success on-error opts))))
|
||||
(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 %))
|
||||
opts {:valid-response? response-validator
|
||||
:timeout-ms timeout-ms}]
|
||||
(utils/http-get url on-success on-error opts)))
|
||||
(http/get url on-success on-error opts)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:http-get
|
||||
|
@ -204,7 +207,6 @@
|
|||
:close-application
|
||||
(fn [] (status/close-application)))
|
||||
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-db
|
||||
|
@ -220,13 +222,13 @@
|
|||
(handlers/register-handler-fx
|
||||
:initialize-app
|
||||
(fn [_ _]
|
||||
{::testfairy-alert nil
|
||||
:dispatch-n [[:initialize-db]
|
||||
[:load-accounts]
|
||||
[:initialize-views]
|
||||
[:listen-to-network-status]
|
||||
[:initialize-crypt]
|
||||
[:initialize-geth]]}))
|
||||
{::testfairy-alert nil
|
||||
:dispatch-n [[:initialize-db]
|
||||
[:load-accounts]
|
||||
[:initialize-views]
|
||||
[:listen-to-network-status]
|
||||
[:initialize-crypt]
|
||||
[:initialize-geth]]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:initialize-db
|
||||
|
@ -250,8 +252,7 @@
|
|||
status-module-initialized? status-node-started?
|
||||
inbox/wnode]
|
||||
:or [network (get app-db :network)
|
||||
wnode (get app-db :inbox/wnode)]
|
||||
:as db} [_ address]]
|
||||
wnode (get app-db :inbox/wnode)]} [_ address]]
|
||||
(let [console-contact (get contacts console-chat-id)]
|
||||
(cond-> (assoc app-db
|
||||
:access-scope->commands-responses access-scope->commands-responses
|
||||
|
@ -332,6 +333,25 @@
|
|||
(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
|
||||
|
|
|
@ -107,20 +107,22 @@
|
|||
:icon-content [components.common/counter {:size 22} 1]}]
|
||||
[profile.components/settings-item-separator]])])
|
||||
|
||||
(defn navigate-to-accounts []
|
||||
(defn navigate-to-accounts [sharing-usage-data?]
|
||||
;; TODO(rasom): probably not the best place for this call
|
||||
(protocol/stop-whisper!)
|
||||
(re-frame/dispatch [:navigate-to :accounts]))
|
||||
(re-frame/dispatch [:navigate-to :accounts])
|
||||
(when sharing-usage-data?
|
||||
(re-frame/dispatch [:unregister-mixpanel-tracking])))
|
||||
|
||||
(defn handle-logout []
|
||||
(defn handle-logout [sharing-usage-data?]
|
||||
(utils/show-confirmation (i18n/label :t/logout-title)
|
||||
(i18n/label :t/logout-are-you-sure)
|
||||
(i18n/label :t/logout) navigate-to-accounts))
|
||||
(i18n/label :t/logout) #(navigate-to-accounts sharing-usage-data?)))
|
||||
|
||||
(defn logout []
|
||||
(defn logout [sharing-usage-data?]
|
||||
[react/view {}
|
||||
[react/touchable-highlight
|
||||
{:on-press handle-logout
|
||||
{:on-press #(handle-logout sharing-usage-data?)
|
||||
:accessibility-label :log-out-button}
|
||||
[react/view profile.components.styles/settings-item
|
||||
[react/text {:style styles/logout-text
|
||||
|
@ -159,7 +161,7 @@
|
|||
:action-fn #(re-frame/dispatch [:switch-dev-mode %])}]])]))
|
||||
|
||||
(defview my-profile []
|
||||
(letsubs [{:keys [public-key] :as current-account} [:get-current-account]
|
||||
(letsubs [{:keys [public-key sharing-usage-data?] :as current-account} [:get-current-account]
|
||||
editing? [:get :my-profile/editing?]
|
||||
changed-account [:get :my-profile/profile]]
|
||||
(let [shown-account (merge current-account changed-account)]
|
||||
|
@ -174,5 +176,5 @@
|
|||
[share-contact-code current-account public-key]]
|
||||
[react/view styles/my-profile-info-container
|
||||
[my-profile-settings current-account]]
|
||||
[logout]
|
||||
[advanced shown-account]]])))
|
||||
[logout sharing-usage-data?]
|
||||
[advanced shown-account]]])))
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
(ns status-im.ui.screens.qr-scanner.styles
|
||||
(:require [status-im.ui.components.styles :refer [color-white]]
|
||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]
|
||||
[status-im.utils.platform :as p]))
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]))
|
||||
|
||||
(def barcode-scanner-container
|
||||
{:flex 1
|
||||
:background-color :white})
|
||||
|
||||
(def barcode-scanner
|
||||
{:flex 1
|
||||
:justify-content :flex-end
|
||||
:align-items :center})
|
||||
{:flex 1})
|
||||
|
||||
(def rectangle-container
|
||||
{:position :absolute
|
||||
|
@ -73,5 +70,5 @@
|
|||
(def import-text
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:color color-white
|
||||
:color colors/white
|
||||
:margin-left 8})
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:help-improve-handler
|
||||
(fn [{db :db} [_ yes?]]
|
||||
(fn [{db :db} [_ yes? address]]
|
||||
(merge (when yes?
|
||||
(accounts/account-update {:db db} {:sharing-usage-data? true}))
|
||||
{:dispatch [:navigate-to-clean :home]})))
|
||||
{:dispatch-n [(when yes? [:register-mixpanel-tracking address])
|
||||
[:account-finalized]]})))
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.ui.screens.usage-data.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.react-native.resources :as resources]
|
||||
|
@ -8,23 +8,24 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]))
|
||||
|
||||
(defview usage-data []
|
||||
[react/view {:style styles/usage-data-view}
|
||||
[status-bar/status-bar {:flat? true}]
|
||||
[react/view {:style styles/logo-container}
|
||||
[components.common/logo styles/logo]
|
||||
[react/image {:source (:analytics-image resources/ui)
|
||||
:style styles/usage-data-image}]]
|
||||
[react/text {:style styles/help-improve-text}
|
||||
(i18n/label :t/help-improve)]
|
||||
[react/view
|
||||
[react/text {:style styles/help-improve-text-description}
|
||||
(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])
|
||||
: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])
|
||||
:label (i18n/label :t/dont-want-to-share)
|
||||
:background? false}]]]])
|
||||
(views/defview usage-data []
|
||||
(views/letsubs [account [:get-current-account]]
|
||||
[react/view {:style styles/usage-data-view}
|
||||
[status-bar/status-bar {:flat? true}]
|
||||
[react/view {:style styles/logo-container}
|
||||
[components.common/logo styles/logo]
|
||||
[react/image {:source (:analytics-image resources/ui)
|
||||
:style styles/usage-data-image}]]
|
||||
[react/text {:style styles/help-improve-text}
|
||||
(i18n/label :t/help-improve)]
|
||||
[react/view
|
||||
[react/text {:style styles/help-improve-text-description}
|
||||
(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)])
|
||||
: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)])
|
||||
:label (i18n/label :t/dont-want-to-share)
|
||||
:background? false}]]]]))
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
(ns status-im.utils.build
|
||||
(:require [cljs.analyzer :as analyzer]))
|
||||
(:require [cljs.analyzer :as analyzer]
|
||||
[clojure.java.shell :as shell]))
|
||||
|
||||
;; Some warnings are unavoidable due to dependencies. For example, reagent 0.6.0
|
||||
;; has a warning in its util.cljs namespace. Adjust this as is necessary and
|
||||
;; unavoidable warnings arise.
|
||||
(def acceptable-warning?
|
||||
#{
|
||||
"Protocol IFn implements method -invoke with variadic signature (&)" ;; reagent 0.6.0 reagent/impl/util.cljs:61
|
||||
})
|
||||
#{"Protocol IFn implements method -invoke with variadic signature (&)"}) ;; reagent 0.6.0 reagent/impl/util.cljs:61
|
||||
|
||||
(defn nil-acceptable-warning [s]
|
||||
(when-not (acceptable-warning? s)
|
||||
|
@ -19,3 +18,6 @@
|
|||
(binding [*out* *err*]
|
||||
(println (analyzer/message env (str "\u001B[31mWARNING\u001B[0m: " s))))
|
||||
(System/exit 1))))
|
||||
|
||||
(defmacro git-short-version []
|
||||
(:out (shell/sh "bash" "-c" "git describe --always")))
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
(ns status-im.utils.build
|
||||
(:require-macros [status-im.utils.build :refer [git-short-version]]))
|
||||
|
||||
(def version (git-short-version))
|
|
@ -33,6 +33,7 @@
|
|||
(def many-whisper-topics-enabled? (enabled? (get-config :MANY_WHISPER_TOPICS_ENABLED 0)))
|
||||
(def rn-bridge-threshold-warnings-enabled? (enabled? (get-config :RN_BRIDGE_THRESHOLD_WARNINGS 0)))
|
||||
(def compile-views-enabled? (enabled? (get-config :COMPILE_VIEWS_ENABLED 0)))
|
||||
(def mixpanel-token (get-config :MIXPANEL_TOKEN))
|
||||
|
||||
(def pow-target (js/parseFloat (get-config :POW_TARGET "0.001")))
|
||||
(def pow-time (js/parseInt (get-config :POW_TIME "1")))
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
(handler db params)
|
||||
db))
|
||||
|
||||
(defn- pretty-print-event [ctx]
|
||||
(let [[first second] (get-coeffect ctx :event)]
|
||||
(if (map? second)
|
||||
first
|
||||
(str first " " second))))
|
||||
|
||||
(def debug-handlers-names
|
||||
"Interceptor which logs debug information to js/console for each event."
|
||||
(->interceptor
|
||||
|
@ -26,13 +32,12 @@
|
|||
[context]
|
||||
(when @pre-event-callback
|
||||
(@pre-event-callback (get-coeffect context :event)))
|
||||
(log/debug "Handling re-frame event: " (first (get-coeffect context :event)))
|
||||
(log/debug "Handling re-frame event: " (pretty-print-event context))
|
||||
context)))
|
||||
|
||||
(defn- check-spec-msg-path-problem [problem]
|
||||
(let [pred (:pred problem)]
|
||||
(str "Spec: " (-> problem :via last) "\n"
|
||||
"Predicate: " (subs (str (:pred problem)) 0 50))))
|
||||
(str "Spec: " (-> problem :via last) "\n"
|
||||
"Predicate: " (subs (str (:pred problem)) 0 50)))
|
||||
|
||||
(defn- check-spec-msg-path-problems [path path-problems]
|
||||
(str "Key path: " path "\n"
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
(ns status-im.utils.http
|
||||
(:require [status-im.constants :as const]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies])
|
||||
(:refer-clojure :exclude [get]))
|
||||
|
||||
;; Default HTTP request timeout ms
|
||||
(def http-request-default-timeout-ms 3000)
|
||||
|
||||
(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)}))
|
||||
(.then (fn [response]
|
||||
(.text response)))
|
||||
(.then (fn [text]
|
||||
(let [json (.parse js/JSON text)
|
||||
obj (js->clj json :keywordize-keys true)]
|
||||
(on-success obj))))
|
||||
(.catch (or on-error
|
||||
(fn [error]
|
||||
(utils/show-popup "Error" (str error))))))))
|
||||
|
||||
(defn get
|
||||
"Performs an HTTP GET request"
|
||||
([url] (get url nil))
|
||||
([url on-success] (get url on-success nil))
|
||||
([url on-success on-error]
|
||||
(get url on-success on-error nil))
|
||||
([url on-success on-error {:keys [valid-response? timeout-ms]}]
|
||||
(-> (rn-dependencies/fetch url
|
||||
(clj->js {:method "GET"
|
||||
:headers {"Cache-Control" "no-cache"}
|
||||
:timeout (or timeout-ms http-request-default-timeout-ms)}))
|
||||
(.then (fn [response]
|
||||
(let [ok? (.-ok response)
|
||||
ok?' (if valid-response?
|
||||
(and ok? (valid-response? response))
|
||||
ok?)]
|
||||
[(.-_bodyText response) ok?'])))
|
||||
(.then (fn [[response ok?]]
|
||||
(cond
|
||||
(and on-success ok?)
|
||||
(on-success response)
|
||||
|
||||
(and on-error (not ok?))
|
||||
(on-error response)
|
||||
|
||||
:else false)))
|
||||
(.catch (or on-error
|
||||
(fn [error]
|
||||
(utils/show-popup "Error" (str error))))))))
|
|
@ -0,0 +1,48 @@
|
|||
(ns status-im.utils.mixpanel
|
||||
(:require-macros [status-im.utils.slurp :as slurp])
|
||||
(:require [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]))
|
||||
|
||||
(def base-url "http://api.mixpanel.com/")
|
||||
(def base-track-url (str base-url "track/"))
|
||||
|
||||
(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 track [id label props]
|
||||
(http/get (build-url id label props)))
|
||||
|
||||
;; Mixpanel events definition
|
||||
|
||||
(def events (reader/read-string (slurp/slurp "./src/status_im/utils/mixpanel_events.edn")))
|
||||
(def event-by-trigger (reduce-kv #(assoc %1 (:trigger %3) %3) {} events))
|
||||
|
||||
(defn matches? [event trigger]
|
||||
(if (= 1 (count trigger))
|
||||
(= (first event) (first trigger))
|
||||
(and
|
||||
(= (first event) (first trigger))
|
||||
(= (second event) (second trigger)))))
|
||||
|
||||
(defn matching-events [event definitions]
|
||||
(reduce-kv #(if (matches? event %2) (conj %1 %3) %1) [] definitions))
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
;; This file is supposed to be edited by Chad.
|
||||
;; Chad loves mixpanel. When Chad was a child he dreamed of being a mixpanel tamer.
|
||||
|
||||
[;; Account creation
|
||||
|
||||
{:label "Account created"
|
||||
:trigger [:account-finalized]}
|
||||
{:label "Account restored"
|
||||
:trigger [:account-recovered]}
|
||||
|
||||
;; Account lifecycle
|
||||
|
||||
{:label "Login"
|
||||
:trigger [:initialize-account]}
|
||||
|
||||
{:label "Logout"
|
||||
:trigger [:navigate-to :accounts]}
|
||||
|
||||
;; Tab navigation
|
||||
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-clean :home]
|
||||
:properties {:target :home}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-tab :home]
|
||||
:properties {:target :home}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-tab :my-profile]
|
||||
:properties {:target :my-profile}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-clean :wallet]
|
||||
:properties {:target :wallet}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-tab :wallet]
|
||||
:properties {:target :wallet}}
|
||||
|
||||
;; New
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-tab :new]
|
||||
:properties {:target :new}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :new-chat]
|
||||
:properties {:target :new-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:scan-qr-code]
|
||||
:properties {:target :new-chat-qr-code}}
|
||||
{:label "Tap"
|
||||
:trigger [:show-profile]
|
||||
:properties {:target :show-profile}}
|
||||
{:label "Tap"
|
||||
:trigger [:open-contact-toggle-list :chat-group]
|
||||
:properties {:target :new-group-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :new-public-chat]
|
||||
:properties {:target :new-public-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :open-dapp]
|
||||
:properties {:target :open-dapp}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :dapp-description]
|
||||
:properties {:target :open-dapp-description}}
|
||||
{:label "Tap"
|
||||
:trigger [:open-dapp-in-browser]
|
||||
:properties {:target :open-selected-dapp}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :new-group]
|
||||
:properties {:target :start-group-chat-next}}
|
||||
{:label "Tap"
|
||||
:trigger [:create-new-public-chat]
|
||||
:properties {:target :create-public-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :new-public-chat]
|
||||
:properties {:target :join-public-chat}}
|
||||
|
||||
;; Chat
|
||||
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-chat]
|
||||
:properties {:target :open-existing-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :browser]
|
||||
:properties {:target :open-existing-dapp}}
|
||||
{:label "Tap"
|
||||
:trigger [:start-chat]
|
||||
:properties {:target :start-chat}}
|
||||
{:label "Tap"
|
||||
:trigger [:send-current-message]
|
||||
:properties {:target :send-current-message}}
|
||||
|
||||
;; Wallet
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :wallet-send-transaction]
|
||||
:properties {:target :wallet-send-transaction}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :wallet-request-transaction]
|
||||
:properties {:target :wallet-request-transaction}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :transactions-history]
|
||||
:properties {:target :transactions-history}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :recent-recipients]
|
||||
:properties {:target :select-recipient
|
||||
:type :recent-recipients}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :recipient-qr-code]
|
||||
:properties {:target :select-recipient
|
||||
:type :recipient-qr-code}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :contact-code]
|
||||
:properties {:target :select-recipient
|
||||
:type :contact-code}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :wallet-send-assets]
|
||||
:properties {:target :wallet-send-assets}}
|
||||
{:label "Tap"
|
||||
:trigger [:wallet.send/toggle-advanced]
|
||||
:properties {:target :wallet-advanced}}
|
||||
{:label "Tap"
|
||||
:trigger [:wallet.send/set-signing?]
|
||||
:properties {:target :wallet-open-sign-transaction}}
|
||||
{:label "Tap"
|
||||
:trigger [:wallet/sign-transaction]
|
||||
:properties {:target :wallet-sign-transaction}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to-clean :wallet]
|
||||
:properties {:target :wallet-got-it}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :wallet-transaction-sent]
|
||||
:properties {:target :wallet-transaction-sent}}
|
||||
|
||||
|
||||
;;Profile
|
||||
{:label "Tap"
|
||||
:trigger [:my-profile/start-editing-profile]
|
||||
:properties {:target :edit-profile}}
|
||||
{:label "Tap"
|
||||
:trigger [:my-profile/update-picture]
|
||||
:properties {:target :edit-image
|
||||
:type :gallery}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :profile-photo-capture]
|
||||
:properties {:target :edit-image
|
||||
:type :capture}}
|
||||
{:label "Tap"
|
||||
:trigger [:navigate-to :profile-qr-viewer]
|
||||
:properties {:target :share-contact-code}}]
|
|
@ -4,11 +4,18 @@
|
|||
[status-im.react-native.js-dependencies :as rn-dependencies]))
|
||||
|
||||
(def platform
|
||||
(when-let [pl (.-Platform rn-dependencies/react-native)]
|
||||
(.-OS pl)))
|
||||
(.-Platform rn-dependencies/react-native))
|
||||
|
||||
(def android? (= platform "android"))
|
||||
(def ios? (= platform "ios"))
|
||||
(def os
|
||||
(when platform
|
||||
(.-OS platform)))
|
||||
|
||||
(def version
|
||||
(when platform
|
||||
(.-Version platform)))
|
||||
|
||||
(def android? (= os "android"))
|
||||
(def ios? (= os "ios"))
|
||||
(def iphone-x? (and ios? (ios/iphone-x-dimensions?)))
|
||||
|
||||
(def platform-specific
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.utils.prices
|
||||
(:require [status-im.utils.utils :as utils]
|
||||
(:require [status-im.utils.http :as http]
|
||||
[status-im.utils.types :as types]))
|
||||
|
||||
;; Responsible for interacting with Cryptocompare API to get current prices for
|
||||
|
@ -25,7 +25,7 @@
|
|||
:last-day (:OPEN24HOUR entry)}))
|
||||
|
||||
(defn get-prices [from to on-success on-error]
|
||||
(utils/http-get
|
||||
(http/get
|
||||
(gen-price-url from to)
|
||||
(fn [resp] (on-success (format-price-resp from to resp)))
|
||||
on-error))
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
(defn wrap-first-time
|
||||
"Allows to avoid
|
||||
\"Use of undeclared Var status-im.utils.platform/platform\"
|
||||
\"Use of undeclared Var status-im.utils.platform/os\"
|
||||
warning. When defstyle or defnstyle is called first time status-im.utils.platform
|
||||
namespace will be explicitly required so that clojurescript compiler will compile
|
||||
it before using status-im.utils.platform/platform in macro"
|
||||
it before using status-im.utils.platform/os in macro"
|
||||
[body]
|
||||
`(do
|
||||
~@[(when @first-time
|
||||
|
@ -18,7 +18,7 @@
|
|||
(defn body [style]
|
||||
`(let [style# ~style
|
||||
common# (dissoc style# :android :ios)
|
||||
platform# (keyword status-im.utils.platform/platform)
|
||||
platform# (keyword status-im.utils.platform/os)
|
||||
platform-specific# (get style# platform#)]
|
||||
(if platform-specific#
|
||||
(merge common# platform-specific#)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.utils.transactions
|
||||
(:require [status-im.utils.utils :as utils]
|
||||
(:require [status-im.utils.http :as http]
|
||||
[status-im.utils.types :as types]))
|
||||
|
||||
(defn- get-network-subdomain [network]
|
||||
|
@ -52,6 +52,6 @@
|
|||
{})))
|
||||
|
||||
(defn get-transactions [network account on-success on-error]
|
||||
(utils/http-get (get-transaction-url network account)
|
||||
#(on-success (format-transactions-response % account))
|
||||
on-error))
|
||||
(http/get (get-transaction-url network account)
|
||||
#(on-success (format-transactions-response % account))
|
||||
on-error))
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
(name s)
|
||||
s))
|
||||
|
||||
(defn to-edn-string [value]
|
||||
(with-out-str (pr value)))
|
||||
|
||||
(defn clj->json [data]
|
||||
(.stringify js/JSON (clj->js data)))
|
||||
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
(ns status-im.utils.utils
|
||||
(:require [status-im.constants :as const]
|
||||
[status-im.i18n :as i18n]
|
||||
[clojure.string :as str]
|
||||
(:require [status-im.i18n :as i18n]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]))
|
||||
|
||||
;; Default HTTP request timeout ms
|
||||
(def http-request-default-timeout-ms 3000)
|
||||
|
||||
(defn show-popup [title content]
|
||||
(.alert (.-Alert rn-dependencies/react-native)
|
||||
title
|
||||
|
@ -47,56 +42,6 @@
|
|||
:onPress on-accept
|
||||
:accessibility-label :yes-button})))))
|
||||
|
||||
(defn http-post
|
||||
"Performs an HTTP POST request"
|
||||
([action data on-success]
|
||||
(http-post action data on-success nil))
|
||||
([action data on-success on-error]
|
||||
(http-post action data on-success on-error nil))
|
||||
([action data on-success on-error {:keys [timeout-ms] :as opts}]
|
||||
(-> (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)}))
|
||||
(.then (fn [response]
|
||||
(.text response)))
|
||||
(.then (fn [text]
|
||||
(let [json (.parse js/JSON text)
|
||||
obj (js->clj json :keywordize-keys true)]
|
||||
(on-success obj))))
|
||||
(.catch (or on-error
|
||||
(fn [error]
|
||||
(show-popup "Error" (str error))))))))
|
||||
|
||||
(defn http-get
|
||||
"Performs an HTTP GET request"
|
||||
([url on-success on-error]
|
||||
(http-get url on-success on-error nil))
|
||||
([url on-success on-error {:keys [valid-response? timeout-ms] :as opts}]
|
||||
(-> (rn-dependencies/fetch url
|
||||
(clj->js {:method "GET"
|
||||
:headers {"Cache-Control" "no-cache"}
|
||||
:timeout (or timeout-ms http-request-default-timeout-ms)}))
|
||||
(.then (fn [response]
|
||||
(let [ok? (.-ok response)
|
||||
ok?' (if valid-response?
|
||||
(and ok? (valid-response? response))
|
||||
ok?)]
|
||||
[(.-_bodyText response) ok?'])))
|
||||
(.then (fn [[response ok?]]
|
||||
(cond
|
||||
ok? (on-success response)
|
||||
|
||||
(and on-error (not ok?))
|
||||
(on-error response)
|
||||
|
||||
:else false)))
|
||||
(.catch (or on-error
|
||||
(fn [error]
|
||||
(show-popup "Error" (str error))))))))
|
||||
|
||||
;; background-timer
|
||||
|
||||
(defn set-timeout [cb ms]
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
(def snoopy-bars #js {:default #js {}})
|
||||
(def snoopy-buffer #js {:default #js {}})
|
||||
(def EventEmmiter #js {})
|
||||
(def fetch #js {})
|
||||
|
||||
(def background-timer #js {:setTimeout js/setTimeout
|
||||
:setInterval js/setInterval
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
[status-im.test.utils.signing-phrase.core]
|
||||
[status-im.test.utils.transducers]
|
||||
[status-im.test.utils.async]
|
||||
[status-im.test.utils.datetime]))
|
||||
[status-im.test.utils.datetime]
|
||||
[status-im.test.utils.mixpanel]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
||||
|
@ -57,4 +58,5 @@
|
|||
'status-im.test.utils.gfycat.core
|
||||
'status-im.test.utils.signing-phrase.core
|
||||
'status-im.test.utils.transducers
|
||||
'status-im.test.utils.datetime)
|
||||
'status-im.test.utils.datetime
|
||||
'status-im.test.utils.mixpanel)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
(ns status-im.test.utils.mixpanel
|
||||
(:require [cljs.test :refer-macros [deftest is testing async]]
|
||||
[status-im.utils.mixpanel :as mixpanel]))
|
||||
|
||||
(deftest events
|
||||
(is (not (nil? mixpanel/events))))
|
||||
|
||||
(deftest matches?
|
||||
(is (true? (mixpanel/matches? [:key] [:key])))
|
||||
(is (false? (mixpanel/matches? [:key1] [:key2])))
|
||||
(is (true? (mixpanel/matches? [:key :subkey] [:key])))
|
||||
(is (false? (mixpanel/matches? [:key] [:key :subkey]))))
|
||||
|
||||
(def definitions {[:key] {:trigger [:key]} [:key :subkey] {:trigger [:key :subkey]}})
|
||||
|
||||
(deftest matching-event
|
||||
(is (empty? (mixpanel/matching-events [:non-existing] definitions)))
|
||||
(is (= 1 (count (mixpanel/matching-events [:key] definitions))))
|
||||
(is (= 2 (count (mixpanel/matching-events [:key :subkey] definitions))))
|
||||
(is (empty? (mixpanel/matching-events [:key1 :another-subkey] definitions))))
|
Loading…
Reference in New Issue