[#4866] intagrate react-navigation

This commit is contained in:
Roman Volosovskyi 2018-08-22 19:16:32 +03:00
parent 486d4684b8
commit 6438a1387b
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
56 changed files with 995 additions and 448 deletions

View File

@ -38,7 +38,8 @@
"react-native-fetch-polyfill"
"react-native-testfairy"
"text-encoding"
"js-sha3"]
"js-sha3"
"react-navigation"]
;; Resoures
:resource-dirs ["resources/images"]

View File

@ -46,7 +46,18 @@
(def text-class (get-class "Text"))
(def text-input-class (get-class "TextInput"))
(def image (get-class "Image"))
(def image-class (get-class "Image"))
(defn valid-source? [source]
(or (not (map? source))
(not (contains? source :uri))
(and (contains? source :uri)
(:uri source))))
(defn image [{:keys [source] :as props}]
(when (valid-source? source)
[image-class props]))
(def switch (get-class "Switch"))
(def check-box (get-class "CheckBox"))
@ -231,6 +242,7 @@
:wallet-send-transaction
:wallet-transaction-sent
:wallet-request-transaction
:wallet-send-transaction-chat
:wallet-send-assets
:wallet-request-assets
:choose-recipient
@ -240,34 +252,40 @@
:wallet-send-transaction-request
:wallet-transaction-fee
:wallet-sign-message-modal
:contact-code) styles/color-blue4
:contact-code
:wallet-onboarding-setup
:wallet-settings-assets
:wallet-modal
:wallet-onboarding-setup-modal)
styles/color-blue4
(:qr-viewer
:recipient-qr-code) "#2f3031"
(:accounts :login
:wallet-transactions-filter) styles/color-white
:transparent)})
children (cond-> children
(#{:wallet
:recipient-qr-code)
"#2f3031"
styles/color-white)})
bottom-background (when (#{:wallet
:recent-recipients
:wallet-send-assets
:wallet-request-assets} current-view)
(conj [view {:background-color styles/color-white
:wallet-request-assets
:wallet-settings-assets
:wallet-modal} current-view)
[view {:background-color styles/color-white
:position :absolute
:bottom 0
:right 0
:left 0
:height 100
:z-index -1000}]))]
:z-index -1000}])
children (conj children bottom-background)]
(apply vector safe-area-view props children))))
(defmethod create-main-screen-view :default [_]
view)
(views/defview main-screen-modal-view [current-view & components]
(views/letsubs [signing? [:get-in [:wallet :send-transaction :show-password-input?]]]
(views/letsubs []
(let [main-screen-view (create-main-screen-view current-view)]
[main-screen-view styles/flex
[keyboard-avoiding-view {:flex 1 :flex-direction :column}
(apply vector view styles/flex components)
(when (and platform/iphone-x? (not signing?))
[view {:flex 0 :height 34}])]])))
(apply vector view styles/flex components)]])))

View File

@ -12,7 +12,8 @@
hickory {:mvn/version "0.7.1"}
com.cognitect/transit-cljs {:mvn/version "0.8.248"}
status-im/pluto {:mvn/version "iteration-2-SNAPSHOT"}
mvxcvi/alphabase {:mvn/version "1.0.0"}}
mvxcvi/alphabase {:mvn/version "1.0.0"}
rasom/cljs-react-navigation {:mvn/version "0.1.4"}}
:aliases
{:dev {:extra-deps

View File

@ -2397,6 +2397,11 @@
"safe-buffer": "5.1.2"
}
},
"clamp": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
"integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
},
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@ -2682,6 +2687,15 @@
"object-assign": "4.1.1"
}
},
"create-react-context": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
"integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
"requires": {
"fbjs": "0.8.17",
"gud": "1.0.0"
}
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -4061,6 +4075,11 @@
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="
},
"gud": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
"integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -4183,6 +4202,11 @@
"minimalistic-crypto-utils": "1.0.1"
}
},
"hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
},
"home-or-tmp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
@ -6036,6 +6060,21 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"path-to-regexp": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
"integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
"requires": {
"isarray": "0.0.1"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
}
}
},
"path-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
@ -6232,6 +6271,15 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"query-string": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz",
"integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==",
"requires": {
"decode-uri-component": "0.2.0",
"strict-uri-encode": "2.0.0"
}
},
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
@ -6358,6 +6406,11 @@
"prop-types": "15.6.0"
}
},
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-native": {
"version": "github:status-im/react-native#8f592d9c1e52fc0d5623f38d21426b83db39f3c3",
"requires": {
@ -6491,6 +6544,27 @@
"resolved": "https://registry.npmjs.org/react-native-dialogs/-/react-native-dialogs-1.0.2.tgz",
"integrity": "sha512-3hH6s67RD6w9MVttqWARnto3wnmSgnwPCzsk4aVaQbFjtgVZQecn+oP+jqj01G6OvxAtuG7aSe62fYGs5xileA=="
},
"react-native-dismiss-keyboard": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz",
"integrity": "sha1-MohiQrPyMX4SHzrrmwpYXiuHm0k="
},
"react-native-drawer-layout": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-1.3.2.tgz",
"integrity": "sha512-fjO0scqbJUfNu2wuEpvywL7DYLXuCXJ2W/zYhWz986rdLytidbys1QGVvkaszHrb4Y7OqO96mTkgpOcP8KWevw==",
"requires": {
"react-native-dismiss-keyboard": "1.0.0"
}
},
"react-native-drawer-layout-polyfill": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/react-native-drawer-layout-polyfill/-/react-native-drawer-layout-polyfill-1.3.2.tgz",
"integrity": "sha512-XzPhfLDJrYHru+e8+dFwhf0FtTeAp7JXPpFYezYV6P1nTeA1Tia/kDpFT+O2DWTrBKBEI8FGhZnThrroZmHIxg==",
"requires": {
"react-native-drawer-layout": "1.3.2"
}
},
"react-native-fetch-polyfill": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/react-native-fetch-polyfill/-/react-native-fetch-polyfill-1.1.2.tgz",
@ -6606,6 +6680,14 @@
}
}
},
"react-native-safe-area-view": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.9.0.tgz",
"integrity": "sha512-y792ScHMzvgwquxL869S9CER4dwiFu/TuCiXdy0xBtygmScMK4eWonnUT65LvOrsSSdr8o6XEK1mbI51h6ozvQ==",
"requires": {
"hoist-non-react-statics": "2.5.5"
}
},
"react-native-scrollable-mixin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/react-native-scrollable-mixin/-/react-native-scrollable-mixin-1.0.1.tgz",
@ -6632,6 +6714,14 @@
"pegjs": "0.10.0"
}
},
"react-native-tab-view": {
"version": "0.0.77",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.77.tgz",
"integrity": "sha512-9vjD4Ly1Zlum1Y4g23ODpi/F3gYIUIsKWrsZO/Oh5cuX1eiB1DRVn11nY1z+j/hsQfhfyW6nDlmySyDvYQvYCA==",
"requires": {
"prop-types": "15.6.0"
}
},
"react-native-tcp": {
"version": "git+https://github.com/status-im/react-native-tcp.git#08e9794f2076e67963e027b42b562c9f4c979b2e",
"requires": {
@ -6691,6 +6781,84 @@
}
}
},
"react-navigation": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-2.12.1.tgz",
"integrity": "sha512-C+do+STPvvd/5LbaDhrZyf1P8tCeffttdlHyIRe1NgGg8Nj93FZHWOThi2hnmEZ75kXsS/JGxox4DDPqYVAxeQ==",
"requires": {
"clamp": "1.0.1",
"create-react-context": "0.2.3",
"hoist-non-react-statics": "2.5.5",
"path-to-regexp": "1.7.0",
"query-string": "6.1.0",
"react-lifecycles-compat": "3.0.4",
"react-native-safe-area-view": "0.9.0",
"react-navigation-deprecated-tab-navigator": "1.3.0",
"react-navigation-drawer": "0.5.0",
"react-navigation-stack": "0.2.3",
"react-navigation-tabs": "0.6.0"
}
},
"react-navigation-deprecated-tab-navigator": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-navigation-deprecated-tab-navigator/-/react-navigation-deprecated-tab-navigator-1.3.0.tgz",
"integrity": "sha512-Cm+qYOPFWbvvcuv0YYX0ioYwLGgw7XAqdhAfpo3sIr3trxRW8871ePmfFOPezjQtz4v6ItjZt6LPgtBAVZoroQ==",
"requires": {
"react-native-tab-view": "0.0.77"
}
},
"react-navigation-drawer": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/react-navigation-drawer/-/react-navigation-drawer-0.5.0.tgz",
"integrity": "sha512-F1y593uC6pqBMGH+Omz75oNODEbxB/s0EGO8QtYwu1NmOOEUuuLA+c14zm+pgMsI4HlDabiHxPkWqsgGz25xVQ==",
"requires": {
"react-native-drawer-layout-polyfill": "1.3.2"
}
},
"react-navigation-stack": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-0.2.3.tgz",
"integrity": "sha512-xjVqiI/ztcQt45jxQ3vfO8Lr+9bVq+0J/lRhMdZCvCDwiyOVuB64wx7qPNJW16pnBBLiI5h6H7uhWE3rAT0r/w=="
},
"react-navigation-tabs": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/react-navigation-tabs/-/react-navigation-tabs-0.6.0.tgz",
"integrity": "sha512-Ax1rujJ51R1Jrz7b5bHUAIgsYC1VrFws+d3hxlPy5dXG84iJdV5dnDFRvdQMDDfDZc+NDx2a223lAYsc3p2+XA==",
"requires": {
"hoist-non-react-statics": "2.5.5",
"prop-types": "15.6.2",
"react-lifecycles-compat": "3.0.4",
"react-native-safe-area-view": "0.7.0",
"react-native-tab-view": "1.0.2"
},
"dependencies": {
"prop-types": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
"requires": {
"loose-envify": "1.3.1",
"object-assign": "4.1.1"
}
},
"react-native-safe-area-view": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.7.0.tgz",
"integrity": "sha512-SjLdW/Th0WVMhyngH4O6yC21S+O4U4AAG3QxBr7fZ2ftgjXSpKbDHAhEpxBdFwei6HsnsC2h9oYMtPpaW9nfGg==",
"requires": {
"hoist-non-react-statics": "2.5.5"
}
},
"react-native-tab-view": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-1.0.2.tgz",
"integrity": "sha512-x8I43V1X7/AyMnIwnqJGMU54LqQRlV6vJ9irbls9asA/axdHIdxagPIV6Jx1ttFe/bPKhFwXL+lRYdYxGyUlWg==",
"requires": {
"prop-types": "15.6.2"
}
}
}
},
"react-proxy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz",
@ -7827,6 +7995,11 @@
"resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-1.0.0.tgz",
"integrity": "sha1-kc8lac5NxQYf6816yyY5SloRR1E="
},
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
},
"string-range": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/string-range/-/string-range-1.2.2.tgz",

View File

@ -58,6 +58,7 @@
"react-native-testfairy": "https://github.com/status-im/react-native-testfairy.git#2.14.1-1",
"react-native-udp": "https://github.com/status-im/react-native-udp.git#2.3.1-1",
"react-native-webview-bridge": "git+https://github.com/status-im/react-native-webview-bridge.git#0.33.16-1",
"react-navigation": "^2.12.1",
"realm": "2.15.3",
"rn-snoopy": "https://github.com/status-im/rn-snoopy.git",
"string_decoder": "0.10.31",

View File

@ -12,7 +12,8 @@
[hickory "0.7.1"]
[com.cognitect/transit-cljs "0.8.248"]
[status-im/pluto "iteration-2-SNAPSHOT"]
[mvxcvi/alphabase "1.0.0"]]
[mvxcvi/alphabase "1.0.0"]
[rasom/cljs-react-navigation "0.1.4"]]
:plugins [[lein-cljsbuild "1.1.7"]
[lein-re-frisk "0.5.8"]
[lein-cljfmt "0.5.7"]

View File

@ -27,4 +27,5 @@
(def snoopy-buffer #js {})
(def background-timer #js {:setTimeout (fn [])})
(def testfairy #js {})
(def react-navigation #js {:NavigationActions #js {}})

View File

@ -26,3 +26,4 @@
(def snoopy-buffer (js/require "rn-snoopy/stream/buffer"))
(def background-timer (.-default (js/require "react-native-background-timer")))
(def testfairy (js/require "react-native-testfairy"))
(def react-navigation (js/require "react-navigation"))

View File

@ -26,10 +26,11 @@
(defn continue-after-wallet-onboarding [db modal? cofx]
(let [transaction (get-in db [:wallet :send-transaction])]
(cond modal? {:dispatch [:navigate-to-modal :wallet-send-transaction-modal]}
(chat-send? transaction) {:db (navigation/navigate-back db)
:dispatch [:navigate-to :wallet-send-transaction-chat]}
:else {:db (navigation/navigate-back db)})))
(if modal?
{:dispatch [:navigate-to-clean :wallet-send-transaction-modal]}
(if-not (chat-send? transaction)
(navigation/navigate-to-clean :wallet cofx)
(navigation/navigate-to-cofx :wallet-send-transaction-modal nil cofx)))))
(defn confirm-wallet-set-up [modal? {:keys [db] :as cofx}]
(handlers-macro/merge-fx

View File

@ -82,7 +82,7 @@
(handlers-macro/merge-fx cofx
{:db (assoc db :accounts/create {:show-welcome? true})
:notifications/request-notifications-permissions nil
:dispatch [:navigate-to-clean :home]}
:dispatch [:navigate-to :home]}
(accounts.update/account-update {:name (:name create)})))
(defn next-step [step password password-confirm {:keys [db] :as cofx}]
@ -95,7 +95,7 @@
(defn step-back [step cofx]
(case step
:enter-password {:db (navigation/navigate-back (:db cofx))}
:enter-password (navigation/navigate-back (:db cofx))
:confirm-password (reset-account-creation cofx)))
;;;; COFX

View File

@ -78,7 +78,7 @@
{:db (assoc-in db [:accounts/login :password] password)}
(navigation/navigate-to-cofx :progress nil)
(user-login))
(navigation/navigate-to-cofx :login nil cofx)))
(navigation/navigate-to-clean :login cofx)))
(re-frame/reg-fx
:accounts.login/login

View File

@ -9,15 +9,17 @@
(defn logout
[{:keys [db] :as cofx}]
(let [{:transport/keys [chats]} db]
(handlers-macro/merge-fx cofx
(handlers-macro/merge-fx
cofx
{:keychain/clear-user-password (get-in db [:account/account :address])
:dev-server/stop nil}
(navigation/navigate-to-clean nil)
(navigation/navigate-to-clean :login)
(transport/stop-whisper)
(init/initialize-keychain))))
(defn show-logout-confirmation []
{:ui/show-confirmation {:title (i18n/label :t/logout-title)
{:ui/show-confirmation
{:title (i18n/label :t/logout-title)
:content (i18n/label :t/logout-are-you-sure)
:confirm-button-text (i18n/label :t/logout)
:on-accept #(re-frame/dispatch [:accounts.logout.ui/logout-confirmed])

View File

@ -11,28 +11,8 @@
[status-im.native-module.core :as status]
[status-im.notifications.core :as notifications]
[status-im.core :as core]
[status-im.utils.snoopy :as snoopy]))
(defn init-back-button-handler! []
(let [new-listener (fn []
;; todo: it might be better always return false from
;; this listener and handle application's closing
;; in handlers
(let [stack (subscribe [:get :navigation-stack])
result-box (subscribe [:get-current-chat-ui-prop :result-box])
webview (subscribe [:get :webview-bridge])
view-id (subscribe [:get :view-id])
chat-id (subscribe [:get-current-chat-id])]
(cond
(and @webview (:can-go-back? @result-box))
(do (.goBack @webview) true)
(< 1 (count @stack))
(do (dispatch [:navigate-back]) true)
:else false)))]
(.addEventListener react/back-handler "hardwareBackPress" new-listener)))
[status-im.utils.snoopy :as snoopy]
[taoensso.timbre :as log]))
(defn app-state-change-handler [state]
(dispatch [:app-state-change state]))
@ -71,6 +51,5 @@
(defn init []
(status/set-soft-input-mode status/adjust-resize)
(init-back-button-handler!)
(core/init app-root)
(snoopy/subscribe!))

View File

@ -1,5 +1,6 @@
(ns status-im.chat.commands.impl.transactions
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require-macros [status-im.utils.views :refer [defview letsubs]]
[status-im.utils.handlers-macro :as handlers-macro])
(:require [clojure.string :as string]
[reagent.core :as reagent]
[re-frame.core :as re-frame]
@ -290,31 +291,36 @@
(preview [_ command-message]
(send-preview command-message))
protocol/Yielding
(yield-control [_ {:keys [amount asset]} {:keys [db]}]
(yield-control [_ {:keys [amount asset]} {:keys [db] :as cofx}]
;; Prefill wallet and navigate there
(let [recipient-contact (get-in db [:contacts/contacts (:current-chat-id db)])
sender-account (:account/account db)
chain (keyword (:chain db))
symbol (keyword asset)
{:keys [decimals]} (tokens/asset-for chain symbol)
{:keys [value error]} (wallet.db/parse-amount amount decimals)]
{:keys [value error]} (wallet.db/parse-amount amount decimals)
next-view-id (if (:wallet-set-up-passed? sender-account)
:wallet-send-transaction-modal
:wallet-onboarding-setup)]
(handlers-macro/merge-fx
cofx
{:db (-> db
(assoc-in [:wallet :send-transaction :amount] (money/formatted->internal value symbol decimals))
(assoc-in [:wallet :send-transaction :amount-text] amount)
(assoc-in [:wallet :send-transaction :amount-error] error)
(update-in [:wallet :send-transaction]
assoc
:amount (money/formatted->internal value symbol decimals)
:amount-text amount
:amount-error error)
(choose-recipient.events/fill-request-details
(transaction-details recipient-contact symbol))
(update-in [:wallet :send-transaction] dissoc :id :password :wrong-password?)
(navigation/navigate-to
(if (:wallet-set-up-passed? sender-account)
:wallet-send-transaction-chat
:wallet-onboarding-setup)))
(update-in [:wallet :send-transaction]
dissoc :id :password :wrong-password?))
;; TODO(janherich) - refactor wallet send events, updating gas price
;; is generic thing which shouldn't be defined in wallet.send, then
;; we can include the utility helper without running into circ-dep problem
:update-gas-price {:web3 (:web3 db)
:success-event :wallet/update-gas-price-success
:edit? false}}))
:edit? false}}
(navigation/navigate-to-cofx next-view-id {}))))
protocol/EnhancedParameters
(enhance-send-parameters [_ parameters cofx]
(-> (inject-network-info parameters cofx)

View File

@ -134,14 +134,18 @@
(defn- navigate-to-chat
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
[chat-id {:keys [navigation-replace?]} {:keys [db] :as cofx}]
[chat-id {:keys [navigation-replace?]} cofx]
(if navigation-replace?
(handlers-macro/merge-fx cofx
(navigation/replace-view :chat)
(handlers-macro/merge-fx
cofx
(navigation/navigate-reset
{:index 1
:actions [{:routeName :home}
{:routeName :chat}]})
(preload-chat-data chat-id))
(handlers-macro/merge-fx cofx
;; TODO janherich - refactor `navigate-to` so it can be used with `merge-fx` macro
{:db (navigation/navigate-to db :chat)}
(handlers-macro/merge-fx
cofx
(navigation/navigate-to-cofx :chat {})
(preload-chat-data chat-id))))
(handlers/register-handler-fx
@ -230,11 +234,11 @@
:confirm-button-text (i18n/label :t/clear)
:on-accept #(re-frame/dispatch [:clear-history])}}))
(defn create-new-public-chat [topic {:keys [db now] :as cofx}]
(handlers-macro/merge-fx cofx
(defn create-new-public-chat [topic cofx]
(handlers-macro/merge-fx
cofx
(models/add-public-chat topic)
(navigation/navigate-to-clean :home)
(navigate-to-chat topic {})
(navigate-to-chat topic {:navigation-replace? true})
(public-chat/join-public-chat topic)))
(handlers/register-handler-fx
@ -259,23 +263,23 @@
(group-name-from-contacts selected-contacts
(:contacts/contacts db)
(:username db)))]
(handlers-macro/merge-fx cofx
(handlers-macro/merge-fx
cofx
{:db (assoc db :group/selected-contacts #{})}
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
(navigation/navigate-to-clean :home)
(navigation/navigate-to-cofx :home nil)
(navigate-to-chat random-id {})
(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
(defn show-profile [identity keep-navigation? {:keys [db] :as cofx}]
(cond->> {:db (assoc db :contacts/identity identity)}
keep-navigation? (navigation/navigate-to-cofx :profile nil)
:else (navigation/navigate-forget :profile)))
(defn show-profile [identity {:keys [db]}]
(navigation/navigate-to-cofx
:profile nil {:db (assoc db :contacts/identity identity)}))
(handlers/register-handler-fx
:show-profile
[re-frame/trim-v]
(fn [cofx [identity keep-navigation?]]
(show-profile identity keep-navigation? cofx)))
(fn [cofx [identity]]
(show-profile identity cofx)))
(handlers/register-handler-fx
:resend-message

View File

@ -30,7 +30,7 @@
[status-im.ui.components.colors :as colors]))
(defview add-contact-bar [contact-identity]
(letsubs [{:keys [hide-contact?] :as contact} [:get-contact-by-identity contact-identity]]
(letsubs [{:keys [hide-contact?] :as contact} [:get-contact-by-identity]]
(when (and (not hide-contact?)
(models.contact/can-add-to-contacts? contact))
[react/view style/add-contact
@ -64,7 +64,7 @@
[toolbar/actions [{:icon :icons/wallet
:icon-opts {:color :black
:accessibility-label :wallet-modal-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-modal])}
:handler #(re-frame/dispatch [:navigate-to :wallet-modal])}
{:icon :icons/options
:icon-opts {:color :black
:accessibility-label :chat-menu-button}
@ -159,9 +159,10 @@
:on-layout (fn [e]
(re-frame/dispatch [:set :layout-height (-> e .-nativeEvent .-layout .-height)]))}
[chat-toolbar public?]
(when (= :chat current-view)
(if (= :chat current-view)
[messages-view-animation
[messages-view group-chat]])
[messages-view group-chat]]
[react/view style/message-view-preview])
[input/container {:text-empty? (string/blank? input-text)}]
(when show-bottom-info?
[bottom-info/bottom-info-view])

View File

@ -62,7 +62,7 @@
(defn initialize-app-db
"Initialize db to initial state"
[{{:keys [status-module-initialized? status-node-started?
[{{:keys [status-module-initialized? status-node-started? view-id
network-status network peers-count peers-summary device-UUID]
:or {network (get app-db :network)}} :db}]
{:db (assoc app-db
@ -73,7 +73,8 @@
:status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?)
:status-node-started? status-node-started?
:network network
:device-UUID device-UUID)})
:device-UUID device-UUID
:view-id view-id)})
(defn initialize-app
[encryption-key cofx]
@ -171,7 +172,7 @@
(when (not= (:view-id db) :create-account)
(handlers-macro/merge-fx cofx
{:notifications/request-notifications-permissions nil}
(navigation/navigate-to-clean :home)
(navigation/navigate-to-cofx :home nil)
(universal-links/process-stored-event)
(notifications/process-stored-event address))))

View File

@ -11,7 +11,8 @@
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.ens :as ens]
[status-im.utils.multihash :as multihash]
[status-im.utils.handlers-macro :as handlers-macro]))
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.navigation :as navigation]))
(defn get-current-url [{:keys [history history-index]}]
(when (and history-index history)
@ -74,11 +75,24 @@
:cb ens-multihash-callback}}
{})))
(defn update-new-browser-and-navigate [host browser cofx]
(defn navigate-to-browser
[{{:keys [view-id]} :db :as cofx}]
(if (= view-id :dapp-description)
(navigation/navigate-reset
{:index 1
:actions [{:routeName :home}
{:routeName :browser}]}
cofx)
(navigation/navigate-to-cofx :browser nil cofx)))
(defn update-new-browser-and-navigate
[host browser {:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
{:dispatch [:navigate-to :browser {:browser-id (:browser-id browser)
:resolving? (ens? host)}]}
{:db (assoc db :browser/options
{:browser-id (:browser-id browser)
:resolving? (ens? host)})}
(navigate-to-browser)
(update-browser-fx browser)
(resolve-multihash-fx host false false)))

View File

@ -124,8 +124,11 @@
webview]
:dispatch [:navigate-back]}
(= method constants/web3-personal-sign)
(assoc :dispatch [:navigate-back])
(= method constants/web3-send-transaction)
(assoc :dispatch-later [{:ms 400 :dispatch [:navigate-to-modal :wallet-transaction-sent-modal]}])))
(assoc :dispatch [:navigate-to-clean :wallet-transaction-sent])))
(defn discard-transaction
[{:keys [db]}]
@ -152,7 +155,7 @@
(update :gas-price str)
(dissoc :message-id :id :gas)))))
(defn handle-transaction-error [db {:keys [code message]}]
(defn handle-transaction-error [{:keys [db]} {:keys [code message]}]
(let [{:keys [dapp-transaction]} (get-in db [:wallet :send-transaction])]
(case code
@ -161,11 +164,13 @@
{:db (-> db
(assoc-in [:wallet :send-transaction :wrong-password?] true))}
(cond-> {:db (-> db
navigation/navigate-back
(cond-> (let [cofx {:db
(-> db
(assoc-in [:wallet :transactions-queue] nil)
(assoc-in [:wallet :send-transaction] {}))
:wallet/show-transaction-error message}
:wallet/show-transaction-error
message}]
(navigation/navigate-back cofx))
dapp-transaction
(web3-error-callback db dapp-transaction message)))))

View File

@ -9,9 +9,10 @@
[status-im.react-native.resources :as resources]))
(defn default-chat-icon [name styles]
(when name
[react/view (:default-chat-icon styles)
[react/text {:style (:default-chat-icon-text styles)}
(string/capitalize (first name))]])
(string/capitalize (first name))]]))
(defn dapp-badge [{:keys [online-view-wrapper online-view online-dot-left online-dot-right]}]
[react/view online-view-wrapper

View File

@ -18,7 +18,7 @@
:style (merge styles/hash-value-text style)}]]])
(defn qr-code-viewer [{:keys [style hint-style footer-style]} value hint legend]
{:pre [(not (nil? value))]}
(if value
(let [{:keys [width height]} @(re-frame/subscribe [:dimensions/window])]
[react/view {:style (merge styles/qr-code style)}
[react/text {:style (merge styles/qr-code-hint hint-style)}
@ -29,4 +29,5 @@
:accessibility-label :qr-code-image}
[qr-code {:value value
:size (- size (* 2 styles/qr-code-padding))}]]))
[footer footer-style legend]]))
[footer footer-style legend]])
[react/view [react/text "no value"]]))

View File

@ -39,7 +39,7 @@
(defn svgimage [{:keys [style source]}]
(let [width (reagent/atom nil)
{:keys [uri k] :or {k 1}} source]
(when (http/url-sanitized? uri)
(when (and source uri (http/url-sanitized? uri))
(fn []
[react/view {:style style
:on-layout #(reset! width (-> % .-nativeEvent .-layout .-width))}

View File

@ -18,7 +18,7 @@
(def default-handler #(re-frame/dispatch [:navigate-back]))
(def home-handler #(re-frame/dispatch [:navigate-to-clean :home]))
(def home-handler #(re-frame/dispatch [:navigate-to :home]))
(def default-back
(back default-handler))

View File

@ -14,7 +14,8 @@
(def group-container
{:flex 1
:flex-direction :column})
:flex-direction :column
:background-color colors/white})
(def chat-name-container
{:margin-top 10})

View File

@ -30,7 +30,7 @@
[react/view add-new.styles/input-container
[react/text-input {:on-change-text #(reset! url-text %)
:on-submit-editing #(do
(re-frame/dispatch [:navigate-to-clean :home])
(re-frame/dispatch [:navigate-to :home])
(re-frame/dispatch [:open-url-in-browser @url-text]))
:placeholder (i18n/label :t/enter-url)
:auto-capitalize :none
@ -62,9 +62,7 @@
:icon :icons/address
:icon-opts {:color colors/blue}
:accessibility-label :open-dapp-button
:on-press #(do
(re-frame/dispatch [:navigate-to-clean :home])
(re-frame/dispatch [:open-url-in-browser dapp-url]))}]
:on-press #(re-frame/dispatch [:open-url-in-browser dapp-url])}]
[components/separator {:margin-left 72}]]
[react/view styles/description-container
[react/i18n-text {:style styles/gray-label :key :description}]

View File

@ -51,3 +51,8 @@
(defstyle delete-button
(assoc button
:background-color colors/red))
(def container
(merge
styles/flex
{:background-color colors/white}))

View File

@ -37,7 +37,7 @@
(let [url (get-in manage-bootnode [:url :value])
id (get-in manage-bootnode [:id :value])
name (get-in manage-bootnode [:name :value])]
[react/view components.styles/flex
[react/view styles/container
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label (if id :t/bootnode-details :t/add-bootnode))]

View File

@ -17,6 +17,7 @@
(spec/def :browser/permissions-queue (spec/nilable any?))
(spec/def :browser/options
(spec/nilable
(allowed-keys
:opt-un [:browser/browser-id
:browser/loading?
@ -25,7 +26,7 @@
:browser/show-tooltip
:browser/show-permission
:browser/permissions-queue
:browser/error?]))
:browser/error?])))
(spec/def :browser/browser
(allowed-keys

View File

@ -71,7 +71,7 @@
[toolbar.view/actions [{:icon :icons/wallet
:icon-opts {:color :black
:accessibility-label :wallet-modal-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-modal])}]]])
:handler #(re-frame/dispatch [:navigate-to :wallet-modal])}]]])
(defn- web-view-error [_ code desc]
(reagent/as-element
@ -90,8 +90,9 @@
(re-frame/dispatch [:update-browser-on-nav-change browser url loading error?]))))
(defn get-inject-js [url]
(when url
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
(get (:inject-js browser-config) domain-name)))
(get (:inject-js browser-config) domain-name))))
(defn navigation [webview browser can-go-back? can-go-forward?]
[react/view styles/toolbar
@ -112,17 +113,15 @@
[react/touchable-highlight {:on-press #(.reload @webview)}
[icons/icon :icons/refresh]]])
(views/defview browser []
(views/letsubs [webview (atom nil)
{:keys [address settings]} [:get-current-account]
{:keys [browser-id dapp? name] :as browser} [:get-current-browser]
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
rpc-url [:get :rpc-url]
network-id [:get-network-id]]
(let [can-go-back? (model/can-go-back? browser)
can-go-forward? (model/can-go-forward? browser)
url (model/get-current-url browser)
opt-in? (:web3-opt-in? settings)]
;; should-component-update is called only when component's props are changed,
;; that's why it can't be used in `brwoser`, because `url` comes from subs
(views/defview browser-component
[{:keys [webview error? url browser browser-id can-go-back? can-go-forward?
url-editing? resolving? network-id address show-permission
show-tooltip opt-in? loading? dapp? rpc-url name]}]
{:should-component-update (fn [_ _ args]
(let [[_ props] args]
(not (nil? (:url props)))))}
[react/view styles/browser
[status-bar/status-bar]
[toolbar webview error? url browser browser-id url-editing?]
@ -162,4 +161,34 @@
(if (= show-tooltip :secure)
(i18n/label :t/browser-secure)
(i18n/label :t/browser-not-secure))
#(re-frame/dispatch [:update-browser-options {:show-tooltip nil}])])])))
#(re-frame/dispatch [:update-browser-options {:show-tooltip nil}])])])
(views/defview browser []
(views/letsubs [webview (atom nil)
{:keys [address settings]} [:get-current-account]
{:keys [browser-id dapp? name] :as browser} [:get-current-browser]
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
rpc-url [:get :rpc-url]
network-id [:get-network-id]]
(let [can-go-back? (model/can-go-back? browser)
can-go-forward? (model/can-go-forward? browser)
url (model/get-current-url browser)
opt-in? (:web3-opt-in? settings)]
[browser-component {:webview webview
:dapp? dapp?
:error? error?
:url url
:browser browser
:browser-id browser-id
:can-go-back? can-go-back?
:can-go-forward? can-go-forward?
:url-editing? url-editing?
:resolving? resolving?
:network-id network-id
:address address
:show-permission show-permission
:show-tooltip show-tooltip
:opt-in? opt-in?
:loading? loading?
:rpc-url rpc-url
:name name}])))

View File

@ -12,10 +12,10 @@
[status-im.utils.utils :as utils]))
(defn add-contact-and-open-chat [whisper-id cofx]
(handlers-macro/merge-fx cofx
(navigation/navigate-to-clean :home)
(handlers-macro/merge-fx
cofx
(models.contact/add-contact whisper-id)
(chat.events/start-chat whisper-id {})))
(chat.events/start-chat whisper-id {:navigation-replace? true})))
(re-frame/reg-cofx
:get-default-contacts

View File

@ -63,10 +63,12 @@
(reg-sub :get-contact-by-identity
:<- [:get-contacts]
(fn [contacts [_ identity]]
:<- [:get-current-chat]
(fn [[all-contacts {:keys [contacts]}] [_ identity]]
(let [identity' (or identity (first contacts))]
(or
(get contacts identity)
(utils.contacts/whisper-id->new-contact identity))))
(get all-contacts identity')
(utils.contacts/whisper-id->new-contact identity')))))
(reg-sub :get-dapp-by-name
:<- [:get-dapps]

View File

@ -64,17 +64,32 @@
(for [{:keys [content view-id accessibility-label count-subscription]} tabs-list]
^{:key view-id} [tab view-id content (= view-id current-view-id) accessibility-label count-subscription])])
(views/defview main-tabs []
(views/letsubs [view-id [:get :view-id]
tab-bar-visible? [:tab-bar-visible?]]
[react/view common.styles/flex
[status-bar.view/status-bar {:type (if (= view-id :wallet) :wallet-tab :main)}]
(views/defview main-container [view-id]
(views/letsubs
[tab-bar-visible? [:tab-bar-visible?]]
;; :should-component-update is called only when props are changed,
;; that's why view-id is passed as a prop here. main-tabs component will be
;; rendered while next screen from stack navigator is shown, so we have
;; to prevent re-rendering to avoid no clause exception in case form
{:should-component-update
(fn [_ _ [_ new-view-id]]
(contains? #{:home :wallet :my-profile} new-view-id))}
[react/view common.styles/main-container
(case view-id
:home [home/home]
:wallet [wallet.main/wallet]
:my-profile [profile.user/my-profile])
:my-profile [profile.user/my-profile]
nil)
(when tab-bar-visible?
[tabs view-id])]]))
[tabs view-id])]))
(defn main-tabs [view-id]
[react/view common.styles/flex
[status-bar.view/status-bar
{:type (if (= view-id :wallet) :wallet-tab :main)}]
[main-container view-id]])
(defn get-main-tab [view-id]
(fn []
[main-tabs view-id]))

View File

@ -1,7 +1,9 @@
(ns status-im.ui.screens.navigation
(:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]))
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.navigation :as navigation]
[taoensso.timbre :as log]))
;; private helper fns
@ -21,16 +23,15 @@
(defn navigate-to-clean
([view-id cofx] (navigate-to-clean view-id cofx nil))
([view-id {:keys [db]} screen-params]
;; TODO (jeluard) Unify all :navigate-to flavours. Maybe accept a map of parameters?
(let [db (cond-> (assoc db :navigation-stack (list))
(log/debug "current view-id " (:view-id db))
(let [db (cond-> db
(seq screen-params)
(assoc-in [:navigation/screen-params view-id] screen-params))]
{:db (push-view db view-id)})))
{:db (push-view db view-id)
::navigate-to-clean view-id})))
(defn replace-view [view-id {:keys [db]}]
{:db (-> (update db :navigation-stack replace-top-element view-id)
(assoc :view-id view-id))})
(defn replace-view [view-id _]
{::navigate-replace view-id})
(defn navigate-forget [view-id {:keys [db]}]
{:db (assoc db :view-id view-id)})
@ -52,19 +53,27 @@
(defn navigate-to-cofx [go-to-view-id screen-params {:keys [db]}]
(let [view-id (:view-id db)
db (cond-> db
db (cond-> (assoc db :view-id go-to-view-id)
(seq screen-params)
(assoc-in [:navigation/screen-params go-to-view-id] screen-params))]
(assoc-in [:navigation/screen-params go-to-view-id]
screen-params))]
{:db (if (= view-id go-to-view-id)
db
(push-view db go-to-view-id))}))
(push-view db go-to-view-id))
::navigate-to go-to-view-id}))
(defn navigate-reset
[{:keys [index actions] :as config} {:keys [db]}]
{:db (assoc db :view-id
(:routeName (get actions index)))
::navigate-reset config})
(defn navigate-to
"DEPRECATED, use navigate-to-cofx above.
Navigates to particular view"
([db go-to-view-id]
(navigate-to db go-to-view-id nil))
([{:keys [view-id] :as db} go-to-view-id screen-params]
([db go-to-view-id screen-params]
(:db (navigate-to-cofx go-to-view-id screen-params {:db db}))))
(def unload-data-interceptor
@ -78,13 +87,47 @@
(def navigation-interceptors
[unload-data-interceptor (re-frame/enrich preload-data!)])
;; effects
(re-frame/reg-fx
::navigate-to
(fn [view-id]
(log/debug :navigate-to view-id)
(navigation/navigate-to (name view-id))))
(re-frame/reg-fx
::navigate-back
(fn []
(log/debug :navigate-back)
(navigation/navigate-back)))
(re-frame/reg-fx
::navigate-replace
(fn [view-id]
(log/debug :navigate-replace view-id)
(navigation/navigate-replace view-id)))
(re-frame/reg-fx
::navigate-reset
(fn [config]
(log/debug :navigate-reset config)
(navigation/navigate-reset config)))
(re-frame/reg-fx
::navigate-to-clean
(fn [view-id]
(log/debug :navigate-to-clean view-id)
(navigation/navigate-reset
{:index 0
:actions [{:routeName view-id}]})))
;; event handlers
(handlers/register-handler-db
(handlers/register-handler-fx
:navigate-to
navigation-interceptors
(fn [db [_ & params]]
(apply navigate-to db params)))
(fn [cofx [_ & [go-to-view-id screen-params]]]
(navigate-to-cofx go-to-view-id screen-params cofx)))
(handlers/register-handler-db
:navigate-to-modal
@ -98,14 +141,11 @@
(fn [cofx [_ view-id]]
(replace-view view-id cofx)))
(defn navigate-back [{:keys [navigation-stack view-id modal] :as db}]
(cond
modal (assoc db :modal nil
:was-modal? true)
(>= 1 (count navigation-stack)) db
:else
(let [[previous-view-id :as navigation-stack'] (pop navigation-stack)
(defn navigate-back
[{{:keys [navigation-stack view-id] :as db} :db}]
(assoc
{::navigate-back nil}
:db (let [[previous-view-id :as navigation-stack'] (pop navigation-stack)
first-in-stack (first navigation-stack)]
(if (= view-id first-in-stack)
(-> db
@ -113,11 +153,11 @@
(assoc :navigation-stack navigation-stack'))
(assoc db :view-id first-in-stack)))))
(handlers/register-handler-db
(handlers/register-handler-fx
:navigate-back
(re-frame/enrich -preload-data!)
(fn [db _]
(navigate-back db)))
(fn [cofx _]
(navigate-back cofx)))
(handlers/register-handler-fx
:navigate-to-clean
@ -132,4 +172,4 @@
{:db (-> db
(assoc :prev-tab-view-id (:view-id db))
(assoc :prev-view-id (:view-id db)))}
(navigate-to-clean view-id))))
(navigate-to-cofx view-id {}))))

View File

@ -25,3 +25,8 @@
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})
(def container
(merge
styles/flex
{:background-color colors/white}))

View File

@ -30,7 +30,7 @@
(views/letsubs [manage-network [:get-manage-network]
is-valid? [:manage-network-valid?]]
(let [custom? (= (get-in manage-network [:chain :value]) :custom)]
[react/view components.styles/flex
[react/view styles/container
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/add-network)]

View File

@ -9,8 +9,7 @@
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.network-settings.styles :as st]
[status-im.ui.screens.network-settings.views :as network-settings]
[status-im.ui.components.colors :as colors]))
[status-im.ui.screens.network-settings.views :as network-settings]))
(views/defview network-details []
(views/letsubs [{:keys [networks/selected-network]} [:get-screen-params]
@ -19,7 +18,7 @@
(let [{:keys [id name config]} selected-network
connected? (= id network)
custom? (seq (filter #(= (:id %) id) (:custom networks)))]
[react/view components.styles/flex
[react/view st/container
[status-bar/status-bar]
[react/view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/network-details)]

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.network-settings.styles
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.ui.components.colors :as colors]))
(:require [status-im.ui.components.colors :as colors]
[status-im.ui.components.styles :as components.styles]))
(def wrapper
{:flex 1
@ -146,3 +147,7 @@
(def delete-button-text
{:color colors/red})
(def container
(merge components.styles/flex
{:background-color colors/white}))

View File

@ -1,5 +1,6 @@
(ns status-im.ui.screens.profile.seed.styles
(:require [status-im.ui.components.colors :as colors]))
(:require [status-im.ui.components.colors :as colors]
[status-im.ui.components.styles :as common.styles]))
(def intro-container
{:flex 1
@ -153,3 +154,8 @@
:font-size 14
:text-align :center
:color colors/gray})
(def backup-seed-container
(merge
common.styles/flex
{:background-color colors/white}))

View File

@ -137,7 +137,7 @@
(defview backup-seed []
(letsubs [current-account [:get-current-account]
{:keys [step first-word second-word error word]} [:get :my-profile/seed]]
[react/keyboard-avoiding-view {:style common.styles/flex}
[react/keyboard-avoiding-view {:style styles/backup-seed-container}
[status-bar/status-bar]
[toolbar/toolbar
nil

View File

@ -83,7 +83,7 @@
value (i18n/label :t/qr-code-public-key-hint) (str value)]]))
(defn- show-qr [contact source value]
#(re-frame/dispatch [:navigate-to-modal :profile-qr-viewer {:contact contact
#(re-frame/dispatch [:navigate-to :profile-qr-viewer {:contact contact
:source source
:value value}]))

View File

@ -5,7 +5,7 @@
[status-im.utils.universal-links.core :as utils.universal-links]
[status-im.ui.components.react :refer [view modal create-main-screen-view] :as react]
[status-im.ui.components.styles :as common-styles]
[status-im.ui.screens.main-tabs.views :refer [main-tabs]]
[status-im.ui.screens.main-tabs.views :as main-tabs]
[status-im.ui.screens.accounts.login.views :refer [login]]
[status-im.ui.screens.accounts.recover.views :refer [recover]]
@ -57,105 +57,271 @@
[status-im.ui.screens.intro.views :refer [intro]]
[status-im.ui.screens.accounts.create.views :refer [create-account]]
[status-im.ui.screens.profile.seed.views :refer [backup-seed]]
[status-im.ui.screens.about-app.views :as about-app]))
[status-im.ui.screens.about-app.views :as about-app]
[status-im.utils.navigation :as navigation]
[reagent.core :as reagent]
[cljs-react-navigation.reagent :as nav-reagent]
[status-im.utils.random :as rand]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.utils.platform :as platform]))
(defn get-main-component [view-id]
(case view-id
:collectibles-list collectibles-list
:intro intro
:create-account create-account
(:home :wallet :my-profile) main-tabs
:browser browser
:open-dapp open-dapp
:dapp-description dapp-description
:wallet-onboarding-setup wallet.onboarding.setup/screen
:wallet-send-transaction send-transaction
:wallet-send-transaction-chat send-transaction
:wallet-transaction-sent transaction-sent
:wallet-request-transaction request-transaction
:wallet-send-transaction-request send-transaction-request
(:transactions-history :unsigned-transactions) wallet-transactions/transactions
:wallet-transaction-details wallet-transactions/transaction-details
:wallet-send-assets wallet.components/send-assets
:wallet-request-assets wallet.components/request-assets
:new add-new
:new-group new-group
:add-participants-toggle-list add-participants-toggle-list
:new-public-chat new-public-chat
:contact-toggle-list contact-toggle-list
:new-chat new-chat
:qr-scanner qr-scanner
:chat chat
:profile profile.contact/profile
:group-chat-profile profile.group-chat/group-chat-profile
:profile-photo-capture profile-photo-capture
:accounts accounts
:login login
:progress progress
:recover recover
:network-settings network-settings
:extensions-settings extensions-settings
:network-details network-details
:edit-network edit-network
:log-level-settings log-level-settings
:fleet-settings fleet-settings
:offline-messaging-settings offline-messaging-settings
:edit-mailserver edit-mailserver
:add-extension add-extension
:show-extension show-extension
:bootnodes-settings bootnodes-settings
:edit-bootnode edit-bootnode
:currency-settings currency-settings
:help-center help-center
:recent-recipients recent-recipients
:recipient-qr-code recipient-qr-code
:contact-code contact-code
:backup-seed backup-seed
:about-app about-app/about-app
[react/view [react/text (str "Unknown view: " view-id)]]))
(defn wrap [view-id component]
(fn []
(let [main-view (create-main-screen-view view-id)]
[main-view common-styles/flex
[component]
[:> navigation/navigation-events
{:on-will-focus
(fn []
(log/debug :on-will-focus view-id)
(re-frame/dispatch [:set :view-id view-id]))}]])))
(defn get-modal-component [modal-view]
(case modal-view
:qr-scanner qr-scanner
:profile-qr-viewer profile.user/qr-viewer
:wallet-modal wallet.main/wallet-modal
:wallet-transactions-filter wallet-transactions/filter-history
:wallet-settings-assets wallet-settings/manage-assets
:wallet-send-transaction-modal send-transaction-modal
:wallet-transaction-sent-modal transaction-sent-modal
:wallet-sign-message-modal sign-message-modal
:wallet-transaction-fee wallet.transaction-fee/transaction-fee
:wallet-onboarding-setup-modal wallet.onboarding.setup/modal
[react/view [react/text (str "Unknown modal view: " modal-view)]]))
(defview main-modal []
(letsubs [modal-view [:get :modal]]
(when modal-view
(defn wrap-modal [modal-view component]
(fn []
(if platform/android?
[view common-styles/modal
[modal {:animation-type :slide
:transparent true
[modal {:transparent true
:animation-type :slide
:on-request-close (fn []
(cond
(#{:wallet-send-transaction-modal
:wallet-sign-message-modal
:wallet-transaction-fee}
:wallet-sign-message-modal}
modal-view)
(dispatch [:wallet/discard-transaction-navigate-back])
:else
(dispatch [:navigate-back])))}
(let [component (get-modal-component modal-view)]
[react/main-screen-modal-view modal-view
[component]])]])))
[component]]]]
[react/main-screen-modal-view modal-view
[component]])))
(defview main []
(letsubs [view-id [:get :view-id]]
{:component-did-mount utils.universal-links/initialize
:component-will-unmount utils.universal-links/finalize
:component-will-update (fn [] (react/dismiss-keyboard!))}
(when view-id
(let [component (get-main-component view-id)
main-screen-view (create-main-screen-view view-id)]
[main-screen-view common-styles/flex
[component]
[main-modal]]))))
(defn stack-screens [screens-map]
(->> screens-map
(map (fn [[k v]]
(let [screen (cond
(map? v)
(let [{:keys [screens config]} v]
(nav-reagent/stack-navigator
(stack-screens screens)
config))
(vector? v)
(let [[_ screen] v]
(nav-reagent/stack-screen
(wrap-modal k screen)))
:else
(nav-reagent/stack-screen (wrap k v)))]
[k {:screen screen}])))
(into {})))
(defn get-main-component2 [view-id]
(log/debug :component2 view-id)
(nav-reagent/switch-navigator
{:intro-login-stack
{:screen
(nav-reagent/stack-navigator
(stack-screens
(cond-> {:login login
:progress progress
:create-account create-account
:recover recover
:accounts accounts}
(= :intro view-id)
(assoc :intro intro)))
(cond-> {:headerMode "none"}
(#{:intro :login} view-id)
(assoc :initialRouteName (name view-id))))}
:chat-stack
{:screen
(nav-reagent/stack-navigator
(stack-screens
{:main-stack
{:screens
{:home (main-tabs/get-main-tab :home)
:chat chat
:profile profile.contact/profile
:new add-new
:new-chat new-chat
:qr-scanner qr-scanner
:new-public-chat new-public-chat
:open-dapp open-dapp
:dapp-description dapp-description
:browser browser}
:config
{:headerMode "none"
:initialRouteName "home"}}
:wallet-modal
(wrap-modal :wallet-modal wallet.main/wallet-modal)
:wallet-send-modal-stack
{:screens
{:wallet-send-transaction-modal
[:modal send-transaction-modal]
:wallet-transaction-sent
[:modal transaction-sent-modal]
:wallet-transaction-fee
[:modal wallet.transaction-fee/transaction-fee]}
:config
{:headerMode "none"
:initialRouteName "wallet-send-transaction-modal"}}
:wallet-send-modal-stack-with-onboarding
{:screens
{:wallet-onboarding-setup-modal
[:modal wallet.onboarding.setup/modal]
:wallet-send-transaction-modal
[:modal send-transaction-modal]
:wallet-transaction-sent
[:modal transaction-sent-modal]
:wallet-transaction-fee
[:modal wallet.transaction-fee/transaction-fee]}
:config
{:headerMode "none"
:initialRouteName "wallet-onboarding-setup-modal"}}
:wallet-sign-message-modal
(wrap-modal :wallet-sign-message-modal sign-message-modal)})
{:mode "modal"
:headerMode "none"
:initialRouteName "main-stack"})}
:wallet-stack
{:screen
(nav-reagent/stack-navigator
{:main-stack
{:screen
(nav-reagent/stack-navigator
(stack-screens
{:wallet (main-tabs/get-main-tab :wallet)
:collectibles-list collectibles-list
:wallet-onboarding-setup wallet.onboarding.setup/screen
:wallet-send-transaction-chat send-transaction
:contact-code contact-code
:send-transaction-stack {:screens {:wallet-send-transaction send-transaction
:recent-recipients recent-recipients
:wallet-transaction-sent transaction-sent
:recipient-qr-code recipient-qr-code
:wallet-send-assets wallet.components/send-assets}
:config {:headerMode "none"}}
:request-transaction-stack {:screens {:wallet-request-transaction request-transaction
:wallet-send-transaction-request send-transaction-request
:wallet-request-assets wallet.components/request-assets
:recent-recipients recent-recipients}
:config {:headerMode "none"}}
:unsigned-transactions wallet-transactions/transactions
:transactions-history wallet-transactions/transactions
:wallet-transaction-details wallet-transactions/transaction-details})
{:headerMode "none"
:initialRouteName "wallet"})}
:wallet-settings-assets
{:screen (nav-reagent/stack-screen
(wrap-modal :wallet-settings-assets wallet-settings/manage-assets))}
:wallet-transaction-fee
{:screen (nav-reagent/stack-screen
(wrap-modal :wallet-transaction-fee
wallet.transaction-fee/transaction-fee))}
:wallet-transactions-filter
{:screen (nav-reagent/stack-screen
(wrap-modal :wallet-transactions-filter
wallet-transactions/filter-history))}}
{:mode "modal"
:headerMode "none"
:initialRouteName "main-stack"})}
:profile-stack
{:screen
(nav-reagent/stack-navigator
{:main-stack
{:screen
(nav-reagent/stack-navigator
(stack-screens
{:my-profile (main-tabs/get-main-tab :my-profile)
:profile-photo-capture profile-photo-capture
:about-app about-app/about-app
:bootnodes-settings bootnodes-settings
:edit-bootnode edit-bootnode
:offline-messaging-settings offline-messaging-settings
:edit-mailserver edit-mailserver
:help-center help-center
:extensions-settings extensions-settings
:add-extension add-extension
:show-extension show-extension
:network-settings network-settings
:network-details network-details
:edit-network edit-network
:log-level-settings log-level-settings
:fleet-settings fleet-settings
:currency-settings currency-settings
:backup-seed backup-seed
:login login
:create-account create-account
:recover recover
:accounts accounts
:qr-scanner qr-scanner})
{:headerMode "none"
:initialRouteName "my-profile"})}
:profile-qr-viewer
{:screen (nav-reagent/stack-screen (wrap-modal :profile-qr-viewer profile.user/qr-viewer))}}
{:mode "modal"
:headerMode "none"
:initialRouteName "main-stack"})}}
{:initialRouteName (if (= view-id :home)
"chat-stack"
"intro-login-stack")}))
(defn get-main-component [view-id]
(case view-id
:new-group new-group
:add-participants-toggle-list add-participants-toggle-list
:contact-toggle-list contact-toggle-list
:group-chat-profile profile.group-chat/group-chat-profile
:contact-code contact-code
[react/view [react/text (str "Unknown view: " view-id)]]))
(defonce rand-label (rand/id))
(defn main []
(let [view-id (re-frame/subscribe [:get :view-id])
main-component (atom nil)]
(reagent/create-class
{:component-did-mount
(fn []
(log/debug :main-component-did-mount @view-id)
(utils.universal-links/initialize))
:component-will-mount
(fn []
(when (and @view-id (not @main-component))
(reset! main-component (get-main-component2 @view-id))))
:component-will-unmount
utils.universal-links/finalize
:component-will-update
(fn []
(when (and @view-id (not @main-component))
(reset! main-component (get-main-component2 @view-id)))
(react/dismiss-keyboard!))
:component-did-update
(fn []
(log/debug :main-component-did-update @view-id))
:reagent-render
(fn []
(when (and @view-id main-component)
[:> @main-component
{:ref (fn [r]
(navigation/set-navigator-ref r)
(when (and
platform/android?
(not (contains? #{:intro :login} @view-id)))
(navigation/navigate-to @view-id)))
;; see https://reactnavigation.org/docs/en/state-persistence.html#development-mode
:persistenceKey (when js/goog.DEBUG rand-label)}]))})))

View File

@ -1,5 +1,6 @@
(ns status-im.ui.screens.wallet.collectibles.styles
(:require [status-im.ui.components.colors :as colors]))
(:require [status-im.ui.components.colors :as colors]
[status-im.ui.components.styles :as styles]))
(def default-collectible
{:padding-left 10
@ -27,3 +28,8 @@
(def details-image
{:flex 1
:margin 10})
(def container
(merge
styles/flex
{:background-color colors/white}))

View File

@ -18,7 +18,7 @@
(defview collectibles-list []
(letsubs [{:keys [name symbol]} [:get-screen-params]
collectibles [:screen-collectibles]]
[react/view {:style component.styles/flex}
[react/view styles/container
[react/view {:style component.styles/flex}
[status-bar/status-bar]
[toolbar/toolbar {}

View File

@ -156,6 +156,7 @@
(views/letsubs [balance [:balance]
network [:network]]
(let [{:keys [name icon decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)]
(when name
[react/view
[cartouche {:disabled? disabled? :on-press #(re-frame/dispatch [:navigate-to (type->view type)])}
(i18n/label :t/wallet-asset)
@ -171,7 +172,7 @@
[react/text {:style (merge styles/text-secondary-content styles/asset-label)}
(str (wallet.utils/format-amount (get balance symbol) decimals))]]]]
(when error
[tooltip/tooltip error {}])])))
[tooltip/tooltip error {}])]))))
(defn- recipient-address [address modal?]
[react/text {:style (merge styles/recipient-address (when-not address styles/recipient-no-address))

View File

@ -9,6 +9,7 @@
[status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.handlers :as handlers]
[status-im.utils.money :as money]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.prices :as prices]
[status-im.utils.transactions :as transactions]
[taoensso.timbre :as log]))
@ -212,7 +213,7 @@
{:db (assoc-in db [:wallet :send-transaction] {:id id
:method method
:from-chat? from-chat?})
:dispatch [:navigate-to-modal :wallet-send-transaction-modal]}))
:dispatch [:navigate-to-clean :wallet-send-transaction-modal]}))
(handlers/register-handler-db
:wallet/update-gas-price-success
@ -241,7 +242,8 @@
(handlers/register-handler-fx
:wallet-setup-navigate-back
(fn [{:keys [db]}]
{:db (-> db
(assoc-in [:wallet :send-transaction] {})
(navigation/navigate-back))}))
(fn [{:keys [db] :as cofx}]
(handlers-macro/merge-fx
cofx
{:db (assoc-in db [:wallet :send-transaction] {})}
(navigation/navigate-back))))

View File

@ -31,7 +31,7 @@
:icon-opts {:color :white
:accessibility-label :options-menu-button}
:options [{:label (i18n/label :t/wallet-manage-assets)
:action #(re-frame/dispatch [:navigate-to-modal :wallet-settings-assets])}]}]]])
:action #(re-frame/dispatch [:navigate-to :wallet-settings-assets])}]}]]])
(defn toolbar-modal [modal-history?]
[react/view

View File

@ -22,7 +22,7 @@
(assert whisper-identity)
;; TODO(janherich) remove this dispatch sequence, there is absolutely no need for that :/
{:dispatch-n [[:navigate-back]
[:navigate-to-clean :home]
[:navigate-to :home]
[:add-chat-loaded-event whisper-identity
[::wallet-send-chat-request (name symbol) (str (money/internal->formatted amount symbol decimals))]]
[:start-chat whisper-identity]]}))

View File

@ -1,4 +1,5 @@
(ns status-im.ui.screens.wallet.send.events
(:require-macros [status-im.utils.handlers-macro :as handlers-macro])
(:require [re-frame.core :as re-frame]
[status-im.chat.commands.sending :as commands-sending]
[status-im.chat.models.message :as models.message]
@ -81,12 +82,12 @@
;; SEND TRANSACTION (SIGN MESSAGE) CALLBACK
(handlers/register-handler-fx
::transaction-completed
(fn [{:keys [db now]} [_ {:keys [result error]}]]
(fn [{:keys [db now] :as cofx} [_ {:keys [result error]}]]
(let [{:keys [id method whisper-identity to symbol amount-text dapp-transaction]} (get-in db [:wallet :send-transaction])
db' (assoc-in db [:wallet :send-transaction :in-progress?] false)]
(if error
;; ERROR
(models.wallet/handle-transaction-error db' error)
(models.wallet/handle-transaction-error (assoc cofx :db db') error)
;; RESULT
(merge
{:db (cond-> (assoc-in db' [:wallet :send-transaction] {})
@ -134,20 +135,23 @@
[:wallet/update-estimated-gas (first params)])
(when-not gas-price
[:wallet/update-gas-price])
[:navigate-to-modal (if wallet-set-up-passed?
:wallet-send-transaction-modal
:wallet-onboarding-setup-modal)]]})
[:navigate-to
(if wallet-set-up-passed?
:wallet-send-modal-stack
:wallet-send-modal-stack-with-onboarding)]]})
;;SIGN MESSAGE
(= method constants/web3-personal-sign)
(let [[address data] (models.wallet/normalize-sign-message-params params)]
(if (and address data)
{:db (assoc-in db' [:wallet :send-transaction] {:id (str (or id message-id))
(let [db'' (assoc-in db' [:wallet :send-transaction]
{:id (str (or id message-id))
:from address
:data data
:dapp-transaction queued-transaction
:method method})
:dispatch [:navigate-to-modal :wallet-sign-message-modal]}
:method method})]
(navigation/navigate-to-cofx
:wallet-sign-message-modal nil {:db db''}))
{:db db'})))))))
(handlers/register-handler-fx
@ -160,9 +164,9 @@
(if-let [send-command (and chat-id (get-in db [:id->command ["send" #{:personal-chats}]]))]
(handlers-macro/merge-fx cofx
(commands-sending/send chat-id send-command params)
(navigation/replace-view :wallet-transaction-sent))
(navigation/navigate-to-clean :wallet-transaction-sent))
(handlers-macro/merge-fx cofx
(navigation/replace-view :wallet-transaction-sent)))))
(navigation/navigate-to-clean :wallet-transaction-sent)))))
(defn set-and-validate-amount-db [db amount symbol decimals]
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
@ -261,9 +265,11 @@
(handlers/register-handler-fx
:close-transaction-sent-screen
(fn [{:keys [db]} [_ chat-id]]
{:dispatch [:navigate-back]
:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]}))
(fn [{:keys [db] :as cofx} [_ chat-id]]
(handlers-macro/merge-fx
cofx
{:dispatch-later [{:ms 400 :dispatch [:check-dapps-transactions-queue]}]}
(navigation/navigate-back))))
(handlers/register-handler-fx
:sync-wallet-transactions

View File

@ -39,7 +39,7 @@
(defn- advanced-cartouche [{:keys [max-fee gas gas-price]}]
[react/view
[wallet.components/cartouche {:on-press #(do (re-frame/dispatch [:wallet.send/clear-gas])
(re-frame/dispatch [:navigate-to-modal :wallet-transaction-fee]))}
(re-frame/dispatch [:navigate-to :wallet-transaction-fee]))}
(i18n/label :t/wallet-transaction-fee)
[react/view {:style styles/advanced-options-text-wrapper
:accessibility-label :transaction-fee-button}

View File

@ -19,7 +19,8 @@
(defn return-to-transaction [modal?]
(if modal?
;;TODO(andrey) artificial navigation stack for modals (should be reworked)
(re-frame/dispatch [:navigate-to-modal :wallet-send-transaction-modal])
;; ^ probably will be fixed with react-navigation
(re-frame/dispatch [:navigate-to-clean :wallet-send-transaction-modal])
(act/default-handler)))
(defn- toolbar [modal? title]

View File

@ -19,7 +19,7 @@
(cond->
{:icon :icons/filter
:icon-opts {:accessibility-label :filters-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-filter])}
:handler #(re-frame/dispatch [:navigate-to :wallet-transactions-filter])}
filter? (assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
(defn- all-checked? [filter-data]

View File

@ -0,0 +1,60 @@
(ns status-im.utils.navigation
(:require [status-im.react-native.js-dependencies :as js-dependencies]))
(def navigation-actions
(when (not status-im.utils.platform/desktop?)
(.-NavigationActions js-dependencies/react-navigation)))
(def navigation-events
(when (not status-im.utils.platform/desktop?)
(.-NavigationEvents js-dependencies/react-navigation)))
(def stack-actions
(when (not status-im.utils.platform/desktop?)
(.-StackActions js-dependencies/react-navigation)))
(def navigator-ref (atom nil))
(defn set-navigator-ref [ref]
(reset! navigator-ref ref))
(defn can-be-called? []
(and @navigator-ref
(not status-im.utils.platform/desktop?)))
(defn navigate-to [route]
(when (can-be-called?)
(.dispatch
@navigator-ref
(.navigate
navigation-actions
#js {:routeName (name route)}))))
;; 'Navigation/REPLACE'
;; https://github.com/react-navigation/react-navigation/blob/master/src/routers/StackActions.js#L5
(defn navigate-replace [route]
(when (can-be-called?)
(.dispatch
@navigator-ref
(.replace
stack-actions
#js {:routeName (name route)}))))
(defn- navigate [params]
(when (can-be-called?)
(.navigate navigation-actions (clj->js params))))
(defn navigate-reset [state]
(when (can-be-called?)
(let [state' (update state :actions #(mapv navigate %))]
(.dispatch
@navigator-ref
(.reset
stack-actions
(clj->js state'))))))
(defn navigate-back []
(when (can-be-called?)
(.dispatch
@navigator-ref
(.back navigation-actions))))

View File

@ -49,7 +49,7 @@
(log/info "universal-links: handling view profile" profile-id)
(if (new-chat.db/own-whisper-identity? db profile-id)
(navigation/navigate-to-cofx :my-profile nil cofx)
(chat.events/show-profile profile-id true cofx)))
(chat.events/show-profile profile-id cofx)))
(defn handle-extension [url cofx]
(log/info "universal-links: handling url profile" url)

View File

@ -48,3 +48,4 @@
(def keychain #js {:setGenericPassword (constantly (.resolve js/Promise true))})
(def secure-random #(.resolve js/Promise (clj->js (range 0 %))))
(def react-navigation #js {:NavigationActions #js {}})

View File

@ -62,21 +62,8 @@
[:shh/post 0 :message :payload :message-ids]))))))
(deftest show-profile-test
(testing "default behaviour"
(testing "it navigates to profile but forgets the navigation"
(testing "Dafault behaviour: navigate to profile"
(let [{:keys [db]} (chat-events/show-profile
"a"
false
{:db {:navigation-stack '(:home)}})]
(is (= "a" (:contacts/identity db)))
(is (= '(:home) (:navigation-stack db)))
(is (= :profile (:view-id db))))))
(testing "keep-navigation? on"
(testing "it navigates to profile and keeps the navigation"
(let [{:keys [db]} (chat-events/show-profile
"a"
true
{:db {:navigation-stack '(:home)}})]
(is (= "a" (:contacts/identity db)))
(is (= '(:profile :home) (:navigation-stack db)))
(is (= :profile (:view-id db)))))))
(is (= "a" (:contacts/identity db))))))

View File

@ -31,8 +31,7 @@
(testing "it loads the profile"
(let [actual (links/handle-url "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"
{:db db})]
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity])))
(is (= :profile (get-in actual [:db :view-id]))))))
(is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity]))))))
(testing "if does nothing because the link is invalid"
(is (= (links/handle-url "status-im://user/CONTACTCODE"
{:db db})