Introduced onboarding sign in

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2018-02-28 14:14:59 +03:00
parent 8b1288e20b
commit eb8557dde8
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
76 changed files with 1225 additions and 999 deletions

5
resources/icons/logo.svg Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="46" viewBox="0 0 144 152">
<g stroke="none" stroke-width="1" fill-rule="evenodd">
<path fill="" d="M41.85,82.81 C61.54,81.7 73.88,86.18 93.57,85.07 C98.4541022,84.8006381 103.305626,84.1080412 108.07,83 C105.16,118.58 79.34,149.68 44.34,151.68 C22.83,152.86 1.33,139.92 0.16,118.86 C-0.98,98.16 15.18,84.31 41.85,82.81 Z M99.53,73.91 C79,75.1 66.1,70.31 45.54,71.5 C40.4407254,71.7827279 35.3770963,72.5223591 30.41,73.71 C33.44,35.69 60.35,2.43 96.94,0.32 C119.39,-0.98 141.83,12.89 143.05,35.39 C144.24,57.51 127.38,72.31 99.53,73.91 Z"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -570,66 +570,6 @@ status.command({
} }
}); });
status.response({
name: "password",
color: "#7099e6",
scope: ["personal-chats", "anonymous", "dapps"],
description: I18n.t('password_description'),
icon: "lock_white",
sequentialParams: true,
params: [
{
name: "password",
type: status.types.PASSWORD,
placeholder: I18n.t('password_placeholder'),
hidden: true
},
{
name: "password-confirmation",
type: status.types.PASSWORD,
placeholder: I18n.t('password_placeholder2'),
hidden: true
}
],
validator: function (params, context) {
if (!params.hasOwnProperty("password-confirmation") || params["password-confirmation"].length === 0) {
if (params.password === null || params.password.length < 6) {
var error = status.components.validationMessage(
I18n.t('password_validation_title'),
I18n.t('password_error')
);
return {markup: error};
}
} else {
if (params.password !== params["password-confirmation"]) {
var error = status.components.validationMessage(
I18n.t('password_validation_title'),
I18n.t('password_error1')
);
return {markup: error};
}
}
},
preview: function (params, context) {
var style = {
marginTop: 5,
marginHorizontal: 0,
fontSize: 14,
color: "black"
};
if (context.platform == "ios") {
style.fontSize = 8;
style.marginTop = 10;
style.marginBottom = 2;
style.letterSpacing = 1;
}
return {markup: status.components.text({style: style}, "●●●●●●●●●●")};
}
});
status.response({ status.response({
name: "grant-permissions", name: "grant-permissions",
scope: ["personal-chats", "anonymous", "registered", "dapps"], scope: ["personal-chats", "anonymous", "registered", "dapps"],

View File

@ -22,11 +22,9 @@
;; this listener and handle application's closing ;; this listener and handle application's closing
;; in handlers ;; in handlers
(let [stack (subscribe [:get :navigation-stack]) (let [stack (subscribe [:get :navigation-stack])
creating? (subscribe [:get :accounts/creating-account?])
result-box (subscribe [:get-current-chat-ui-prop :result-box]) result-box (subscribe [:get-current-chat-ui-prop :result-box])
webview (subscribe [:get :webview-bridge])] webview (subscribe [:get :webview-bridge])]
(cond (cond
@creating? true
(and @webview (:can-go-back? @result-box)) (and @webview (:can-go-back? @result-box))
(do (.goBack @webview) true) (do (.goBack @webview) true)

View File

@ -2,7 +2,6 @@
(:require [status-im.ui.components.styles :refer [default-chat-color]] (:require [status-im.ui.components.styles :refer [default-chat-color]]
[status-im.utils.random :as random] [status-im.utils.random :as random]
[status-im.constants :as const] [status-im.constants :as const]
[status-im.chat.constants :as chat-const]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[clojure.string :as string])) [clojure.string :as string]))
@ -16,51 +15,6 @@
:content content :content content
:content-type content-type}) :content-type content-type})
(def shake-your-phone-message
(console-message {:content (i18n/label :t/shake-your-phone)
:content-type const/text-content-type}))
(def account-generation-message
(console-message {:message-id chat-const/crazy-math-message-id
:content (i18n/label :t/account-generation-message)
:content-type const/text-content-type}))
(def move-to-internal-failure-message
(console-message {:message-id chat-const/move-to-internal-failure-message-id
:content {:command "grant-permissions"
:content (i18n/label :t/move-to-internal-failure-message)}
:content-type const/content-type-command-request}))
(defn passphrase-messages [mnemonic signing-phrase crazy-math-message?]
[(console-message {:message-id chat-const/passphrase-message-id
:content (if crazy-math-message?
(i18n/label :t/phew-here-is-your-passphrase)
(i18n/label :t/here-is-your-passphrase))
:content-type const/text-content-type})
(console-message {:message-id (random/id)
:content mnemonic
:content-type const/text-content-type})
(console-message {:message-id chat-const/signing-phrase-message-id
:content (i18n/label :t/here-is-your-signing-phrase)
:content-type const/text-content-type})
(console-message {:message-id (random/id)
:content signing-phrase
:content-type const/text-content-type})])
(def intro-status-message
(console-message {:message-id chat-const/intro-status-message-id
:content (i18n/label :t/intro-status)
:content-type const/content-type-status}))
(def intro-message1
(console-message {:message-id chat-const/intro-message1-id
:content {:command "password"
:content (i18n/label :t/intro-message1)}
:content-type const/content-type-command-request}))
(def chat (def chat
{:chat-id const/console-chat-id {:chat-id const/console-chat-id
:name (string/capitalize const/console-chat-id) :name (string/capitalize const/console-chat-id)

View File

@ -5,18 +5,10 @@
(def arg-wrapping-char "\"") (def arg-wrapping-char "\"")
(def input-height 56) (def input-height 56)
(def max-input-height 66)
(def input-spacing-top 16) (def input-spacing-top 16)
(def console-chat-id "console") (def console-chat-id "console")
(def crazy-math-message-id "crazy-math-message")
(def move-to-internal-failure-message-id "move-to-internal-failure-message")
(def passphrase-message-id "passphraze-message")
(def signing-phrase-message-id "signing-phrase-message")
(def intro-status-message-id "intro-status")
(def intro-message1-id "intro-message1")
;; TODO(janherich): figure out something better then this ;; TODO(janherich): figure out something better then this
(def send-command-ref ["transactor" :command 83 "send"]) (def send-command-ref ["transactor" :command 83 "send"])
(def request-command-ref ["transactor" :command 83 "request"]) (def request-command-ref ["transactor" :command 83 "request"])
(def phone-command-ref ["console" :command 50 "phone"])

View File

@ -7,7 +7,6 @@
[status-im.protocol.core :as protocol] [status-im.protocol.core :as protocol]
[status-im.chat.models :as models] [status-im.chat.models :as models]
[status-im.chat.console :as console] [status-im.chat.console :as console]
[status-im.chat.constants :as chat.constants]
[status-im.data-store.chats :as chats] [status-im.data-store.chats :as chats]
[status-im.data-store.messages :as messages] [status-im.data-store.messages :as messages]
[status-im.data-store.pending-messages :as pending-messages] [status-im.data-store.pending-messages :as pending-messages]
@ -153,18 +152,15 @@
(update-in db [:chats chat-id :messages message-id] assoc :appearing? false))) (update-in db [:chats chat-id :messages message-id] assoc :appearing? false)))
(defn init-console-chat (defn init-console-chat
[{:keys [chats] :accounts/keys [current-account-id] :as db}] [{:keys [chats] :as db}]
(if (chats constants/console-chat-id) (if (chats constants/console-chat-id)
{:db db} {:db db}
(cond-> {:db (-> db {:db (-> db
(assoc :current-chat-id constants/console-chat-id) (assoc :current-chat-id constants/console-chat-id)
(update :chats assoc constants/console-chat-id console/chat)) (update :chats assoc constants/console-chat-id console/chat))
:dispatch-n [[:add-contacts [console/contact]]] :dispatch [:add-contacts [console/contact]]
:save-chat console/chat :save-chat console/chat
:save-all-contacts [console/contact]} :save-all-contacts [console/contact]}))
(not current-account-id)
(update :dispatch-n concat [[:chat-received-message/add-when-commands-loaded console/intro-message1]]))))
(handlers/register-handler-fx (handlers/register-handler-fx
:init-console-chat :init-console-chat
@ -186,11 +182,6 @@
get-stored-messages get-stored-messages
stored-unviewed-messages stored-unviewed-messages
stored-message-ids]} _] stored-message-ids]} _]
(let [{:accounts/keys [account-creation?]} db
load-default-contacts-event [:load-default-contacts!]]
(if account-creation?
{:db db
:dispatch load-default-contacts-event}
(let [chat->message-id->request (reduce (fn [acc {:keys [chat-id message-id] :as request}] (let [chat->message-id->request (reduce (fn [acc {:keys [chat-id message-id] :as request}]
(assoc-in acc [chat-id message-id] request)) (assoc-in acc [chat-id message-id] request))
{} {}
@ -210,7 +201,7 @@
(assoc :chats chats (assoc :chats chats
:deleted-chats inactive-chat-ids) :deleted-chats inactive-chat-ids)
init-console-chat init-console-chat
(update :dispatch-n conj load-default-contacts-event))))))) (update :dispatch-n conj [:load-default-contacts!])))))
(handlers/register-handler-fx (handlers/register-handler-fx
:send-seen! :send-seen!
@ -232,28 +223,6 @@
:message-id message-id} :message-id message-id}
group-chat (assoc :group-id chat-id))}))))) group-chat (assoc :group-id chat-id))})))))
(handlers/register-handler-fx
:show-mnemonic
[re-frame/trim-v]
(fn [{:keys [db]} [mnemonic signing-phrase]]
(let [crazy-math-message? (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/crazy-math-message-id)
messages-events (->> (console/passphrase-messages mnemonic signing-phrase crazy-math-message?)
(mapv #(vector :chat-received-message/add %)))]
{:dispatch-n messages-events})))
;; TODO(alwx): can be simplified
(handlers/register-handler-fx
:account-generation-message
(fn [{:keys [db]} _]
(when-not (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/passphrase-message-id)
{:dispatch [:chat-received-message/add console/account-generation-message]})))
(handlers/register-handler-fx
:move-to-internal-failure-message
(fn [{:keys [db]} _]
(when-not (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/move-to-internal-failure-message-id)
{:dispatch [:chat-received-message/add console/move-to-internal-failure-message]})))
(handlers/register-handler-fx (handlers/register-handler-fx
:browse-link-from-message :browse-link-from-message
(fn [_ [_ link]] (fn [_ [_ link]]

View File

@ -1,7 +1,5 @@
(ns status-im.chat.events.console (ns status-im.chat.events.console
(:require [re-frame.core :as re-frame] (:require [status-im.constants :as constants]
[status-im.utils.handlers :as handlers]
[status-im.constants :as const]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.chat.console :as console-chat] [status-im.chat.console :as console-chat]
[status-im.ui.screens.accounts.events :as accounts-events] [status-im.ui.screens.accounts.events :as accounts-events]
@ -24,13 +22,13 @@
(console-chat/console-message (console-chat/console-message
{:message-id id {:message-id id
:content (str type ": " message) :content (str type ": " message)
:content-type const/text-content-type})) :content-type constants/text-content-type}))
messages random-id-seq)] messages random-id-seq)]
(conj message-events (conj message-events
(console-chat/console-message (console-chat/console-message
{:message-id (first random-id-seq) {:message-id (first random-id-seq)
:content (str content) :content (str content)
:content-type const/text-content-type}))) :content-type constants/text-content-type})))
(log/debug "ignoring command: " name)))))) (log/debug "ignoring command: " name))))))
(defn faucet-base-url->url [url] (defn faucet-base-url->url [url]
@ -40,15 +38,11 @@
[:chat-received-message/add [:chat-received-message/add
(console-chat/console-message {:message-id message-id (console-chat/console-message {:message-id message-id
:content content :content content
:content-type const/text-content-type})]) :content-type constants/text-content-type})])
(def console-commands->fx (def console-commands->fx
{"password" {"faucet"
(fn [{:keys [db]} {:keys [params]}] (fn [{:keys [db random-id]} {:keys [params]}]
(accounts-events/create-account db (:password params)))
"faucet"
(fn [{:keys [db random-id]} {:keys [params id]}]
(let [{:accounts/keys [accounts current-account-id]} db (let [{:accounts/keys [accounts current-account-id]} db
current-address (get-in accounts [current-account-id :address]) current-address (get-in accounts [current-account-id :address])
faucet-url (faucet-base-url->url (:url params))] faucet-url (faucet-base-url->url (:url params))]
@ -64,7 +58,7 @@
(i18n/label :t/faucet-error)))}})) (i18n/label :t/faucet-error)))}}))
"debug" "debug"
(fn [{:keys [db random-id now] :as cofx} {:keys [params id]}] (fn [{:keys [db random-id now]} {:keys [params]}]
(let [debug? (= "On" (:mode params))] (let [debug? (= "On" (:mode params))]
(-> {:db db} (-> {:db db}
(accounts-events/account-update {:debug? debug? (accounts-events/account-update {:debug? debug?
@ -75,10 +69,10 @@
(console-chat/console-message (console-chat/console-message
{:message-id random-id {:message-id random-id
:content (i18n/label :t/debug-enabled) :content (i18n/label :t/debug-enabled)
:content-type const/text-content-type})]] :content-type constants/text-content-type})]]
[[:stop-debugging]])))))}) [[:stop-debugging]])))))})
(def commands-names (set (keys console-commands->fx))) (def commands-names (set (keys console-commands->fx)))
(def commands-with-delivery-status (def commands-with-delivery-status
(disj commands-names "password" "faucet" "debug")) (disj commands-names "faucet" "debug"))

View File

@ -41,16 +41,6 @@
;; regular non command message, we can add it right away ;; regular non command message, we can add it right away
(message-model/receive cofx message))))) (message-model/receive cofx message)))))
;; TODO janherich: get rid of this special case once they hacky app start-up sequence is refactored
(handlers/register-handler-fx
:chat-received-message/add-when-commands-loaded
message-model/receive-interceptors
(fn [{:keys [db] :as cofx} [{:keys [chat-id] :as message}]]
(if (and (:status-node-started? db)
(get-in db [:contacts/contacts chat-id :jail-loaded?]))
(message-model/receive cofx message)
{:dispatch-later [{:ms 400 :dispatch [:chat-received-message/add-when-commands-loaded message]}]})))
;; TODO(alwx): refactor this when status-im.commands.handlers.jail is refactored ;; TODO(alwx): refactor this when status-im.commands.handlers.jail is refactored
(handlers/register-handler-fx (handlers/register-handler-fx
:chat-received-message/bot-response :chat-received-message/bot-response

View File

@ -35,16 +35,11 @@
(defview chat-toolbar [public?] (defview chat-toolbar [public?]
(letsubs [accounts [:get-accounts] (letsubs [accounts [:get-accounts]
creating? [:get :accounts/creating-account?]
{:keys [group-chat name chat-id]} [:get-current-chat]] {:keys [group-chat name chat-id]} [:get-current-chat]]
[react/view [react/view
[status-bar/status-bar] [status-bar/status-bar]
[toolbar/toolbar {} [toolbar/toolbar {}
(when-not creating? toolbar/default-nav-back
(if (empty? accounts)
[toolbar/nav-clear-text {:handler #(re-frame/dispatch [:navigate-to-modal :recover-modal])}
(i18n/label :t/recover)]
toolbar/default-nav-back))
[toolbar-content/toolbar-content-view] [toolbar-content/toolbar-content-view]
[toolbar/actions [{:icon :icons/options [toolbar/actions [{:icon :icons/options
:icon-opts {:color :black} :icon-opts {:color :black}

View File

@ -9,7 +9,8 @@
[status-im.commands.utils :as commands-utils] [status-im.commands.utils :as commands-utils]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.i18n :as i18n])) [status-im.i18n :as i18n]
[status-im.constants :as const]))
(reg-sub :get-chats :chats) (reg-sub :get-chats :chats)
@ -51,11 +52,15 @@
platform/ios? kb-height platform/ios? kb-height
:default 0))) :default 0)))
(defn active-chats [[_ chat]]
;;TODO (andrey) console should be shown in dev mode only, will be done soon
(and (:is-active chat))) ;(not= const/console-chat-id (:chat-id chat))))
(reg-sub (reg-sub
:get-active-chats :get-active-chats
:<- [:get-chats] :<- [:get-chats]
(fn [chats] (fn [chats]
(into {} (filter (comp :is-active second)) chats))) (into {} (filter active-chats chats))))
(reg-sub (reg-sub
:get-chat :get-chat

View File

@ -66,11 +66,9 @@
show-actions? [:get-current-chat-ui-prop :show-actions?] show-actions? [:get-current-chat-ui-prop :show-actions?]
accounts [:get-accounts] accounts [:get-accounts]
contact [:get-in [:contacts/contacts @chat-id]] contact [:get-in [:contacts/contacts @chat-id]]
sync-state [:sync-state] sync-state [:sync-state]]
creating? [:get :accounts/creating-account?]]
[react/view (st/chat-name-view (or (empty? accounts) [react/view (st/chat-name-view (or (empty? accounts)
show-actions? show-actions?))
creating?))
(let [chat-name (if (string/blank? name) (let [chat-name (if (string/blank? name)
(generate-gfy public-key) (generate-gfy public-key)
(or (i18n/get-contact-translated chat-id :name name) (or (i18n/get-contact-translated chat-id :name name)

View File

@ -4,7 +4,8 @@
[status-im.data-store.realm.schemas.base.v3.core :as v3] [status-im.data-store.realm.schemas.base.v3.core :as v3]
[status-im.data-store.realm.schemas.base.v4.core :as v4] [status-im.data-store.realm.schemas.base.v4.core :as v4]
[status-im.data-store.realm.schemas.base.v5.core :as v5] [status-im.data-store.realm.schemas.base.v5.core :as v5]
[status-im.data-store.realm.schemas.base.v6.core :as v6])) [status-im.data-store.realm.schemas.base.v6.core :as v6]
[status-im.data-store.realm.schemas.base.v7.core :as v7]))
;; put schemas ordered by version ;; put schemas ordered by version
(def schemas [{:schema v1/schema (def schemas [{:schema v1/schema
@ -24,4 +25,7 @@
:migration v5/migration} :migration v5/migration}
{:schema v6/schema {:schema v6/schema
:schemaVersion 6 :schemaVersion 6
:migration v6/migration}]) :migration v6/migration}
{:schema v7/schema
:schemaVersion 7
:migration v7/migration}])

View File

@ -0,0 +1,26 @@
(ns status-im.data-store.realm.schemas.base.v7.account)
(def schema {:name :account
:primaryKey :address
:properties {:address :string
:public-key :string
:updates-public-key {:type :string
:optional true}
:updates-private-key {:type :string
:optional true}
:name {:type :string :optional true}
:email {:type :string :optional true}
:status {:type :string :optional true}
:debug? {:type :bool :default false}
:photo-path :string
:signing-phrase {:type :string}
:last-updated {:type :int :default 0}
:last-sign-in {:type :int :default 0}
:signed-up? {:type :bool
:default false}
:network :string
:networks {:type :list
:objectType :network}
:wnode :string
:settings {:type :string}
:sharing-usage-data? {:type :bool :default false}}})

View File

@ -0,0 +1,10 @@
(ns status-im.data-store.realm.schemas.base.v7.core
(:require [status-im.data-store.realm.schemas.base.v4.network :as network]
[status-im.data-store.realm.schemas.base.v7.account :as account]
[taoensso.timbre :as log]))
(def schema [network/schema
account/schema])
(defn migration [old-realm new-realm]
(log/debug "migrating v7 base database: " old-realm new-realm))

View File

@ -22,4 +22,6 @@
(def ui (def ui
{:empty-hashtags (js/require "./resources/images/ui/empty-hashtags.png") {:empty-hashtags (js/require "./resources/images/ui/empty-hashtags.png")
:empty-recent (js/require "./resources/images/ui/empty-recent.png")}) :empty-recent (js/require "./resources/images/ui/empty-recent.png")
:analytics-image (js/require "./resources/images/ui/analytics-image.png")
:welcome-image (js/require "./resources/images/ui/welcome-image.png")})

View File

@ -28,6 +28,26 @@
:camera-access-error "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected." :camera-access-error "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected."
:photos-access-error "To grant the required photos permission, please go to your system settings and make sure that Status > Photos is selected." :photos-access-error "To grant the required photos permission, please go to your system settings and make sure that Status > Photos is selected."
;;sign in
:intro-text "Status is an open source decentralized chat and Ethereum browser"
:intro-text-description "Status is built with the help of the community to help you use all the benefits of decentralized web in your mobile phone"
:create-account "Create account"
:already-have-account "I already have an account"
:creating-your-account "Creating your account on the blockchain. We can't touch it, no one can, except for you!"
:password-placeholder "Type your password"
:password-placeholder2 "Confirm your password"
:name-placeholder "Enter your full name…"
:password_error1 "Password confirmation doesn't match password."
:password-description "You'll need this password to open the app, confirm transactions and whenever you need to regain access on a new device or install."
:name-description "This will be the name everybody who uses Status will see. You can change it later."
:other-accounts "Other accounts"
:sign-you-in "Signing you in…"
:help-improve "Help improve Status \n by sharing usage data"
:help-improve-description "We strive to collect only what we need to understand how and where we can improve Status"
:share-usage-data "Share usage data"
:dont-want-to-share "No, i don't want to share"
;;drawer ;;drawer
:switch-users "Switch users" :switch-users "Switch users"
:logout-title "Log out?" :logout-title "Log out?"
@ -37,6 +57,9 @@
;;home ;;home
:home "Home" :home "Home"
:no-recent-chats "There are no recent Chats or DApps here yet.\nUse the “Plus” button to see the list of Dapps or discover people to chat with"
:welcome-to-status "Welcome to Status"
:welcome-to-status-description "Here you can chat with people in a secure private chat, browse and interact with DApps. Use the “Plus” icon above to explore Status"
;;chat ;;chat
:is-typing "is typing" :is-typing "is typing"
@ -271,6 +294,7 @@
:password "Password" :password "Password"
:sign-in-to-status "Sign in to Status" :sign-in-to-status "Sign in to Status"
:sign-in "Sign in" :sign-in "Sign in"
:sign-in-to-another "Sign in to another account"
:wrong-password "Wrong password" :wrong-password "Wrong password"
:enter-password "Enter password" :enter-password "Enter password"
@ -278,10 +302,13 @@
:passphrase "Passphrase" :passphrase "Passphrase"
:recover "Recover" :recover "Recover"
:twelve-words-in-correct-order "12 words in correct order" :twelve-words-in-correct-order "12 words in correct order"
:enter-12-words "Enter the 12 words of your seed phrase"
;;accounts ;;accounts
:recover-access "Recover access" :recover-access "Recover access"
:create-new-account "Create new account" :create-new-account "Create new account"
:add-existing-account "Add existing account"
;;wallet-qr-code ;;wallet-qr-code
:done "Done" :done "Done"

View File

@ -31,7 +31,6 @@
:android {:padding-top 8 :android {:padding-top 8
:padding-bottom 8}}) :padding-bottom 8}})
(def action-button-label-disabled (def action-button-label-disabled
(merge action-button-label (merge action-button-label
{:color styles/color-gray4})) {:color styles/color-gray4}))

View File

@ -1,4 +1,5 @@
(ns status-im.ui.components.colors) (ns status-im.ui.components.colors
(:require [clojure.string :as string]))
(def white "#ffffff") (def white "#ffffff")
(def white-light-transparent "rgba(255, 255, 255, 0.1)") ;; Used as icon background color for a dark foreground (def white-light-transparent "rgba(255, 255, 255, 0.1)") ;; Used as icon background color for a dark foreground
@ -7,11 +8,19 @@
(def black "#000000") ;; Used as the default text color (def black "#000000") ;; Used as the default text color
(def black-transparent "#00000020") ;; Used as background color for rounded button on dark background (def black-transparent "#00000020") ;; Used as background color for rounded button on dark background
(def gray "#939ba1") ;; Used as a background for a light foreground and as section header and secondary text color (def gray "#939ba1") ;; Used as a background for a light foreground and as section header and secondary text color
(def gray-icon "#6e777e") ;; Used for forward icon in accounts
(def gray-light "#e8ebec") ;; Used as divider color (def gray-light "#e8ebec") ;; Used as divider color
(def gray-lighter "#eef2f5") ;; Used as a background or shadow (def gray-lighter "#eef2f5") ;; Used as a background or shadow
(def blue "#4360df") ;; Used as main wallet color (def blue "#4360df") ;; Used as main wallet color, and ios home add button
(def blue-transparent "rgba(67, 96, 223, 0.10)") ;;used as shadow for blue elements
(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions (def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions
(def red-light "#ffe5ea") ;; error tooltip
(def text-light-gray "#212121") ;; Used for labels (home items) (def text-light-gray "#212121") ;; Used for labels (home items)
(defn alpha [hex opacity]
(let [hex (string/replace hex #"#" "")
r (js/parseInt (subs hex 0 2) 16)
g (js/parseInt (subs hex 2 4) 16)
b (js/parseInt (subs hex 4 6) 16)]
(str "rgba(" r "," g "," b "," opacity")")))
(def text black) (def text black)

View File

@ -7,7 +7,9 @@
[status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.colors :as colors]))
(defn top-shadow [] (defn top-shadow []
(when platform/android? (when platform/android?
@ -63,3 +65,25 @@
(if (ethereum/testnet? network-id) (if (ethereum/testnet? network-id)
(i18n/label :t/testnet-text {:testnet (get-in ethereum/chains [(ethereum/chain-id->chain-keyword network-id) :name] "Unknown")}) (i18n/label :t/testnet-text {:testnet (get-in ethereum/chains [(ethereum/chain-id->chain-keyword network-id) :name] "Unknown")})
(i18n/label :t/mainnet-text))]]])) (i18n/label :t/mainnet-text))]]]))
(defn logo
([] (logo nil))
([{:keys [size icon-size shadow?] :or {shadow? true}}]
[react/view {:style (styles/logo-container size shadow?)}
[icons/icon :icons/logo (styles/logo icon-size)]]))
(defn bottom-button [{:keys [label disabled? on-press forward?]}]
[react/touchable-highlight {:on-press on-press :disabled disabled?}
[react/view (styles/bottom-button disabled?)
[react/text {:style styles/bottom-button-label
:uppercase? platform/android?}
(or label (i18n/label :t/next))]
(when forward?
[icons/icon :icons/forward {:color colors/blue}])]])
(defn button [{:keys [on-press label background? style] :or {background? true}}]
[react/touchable-highlight {:on-press on-press}
[react/view {:style (styles/button style background?)}
[react/text {:uppercase? platform/android?
:style styles/button-label}
label]]])

View File

@ -1,5 +1,5 @@
(ns status-im.ui.components.common.styles (ns status-im.ui.components.common.styles
(:require-macros [status-im.utils.styles :refer [defstyle]]) (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.ui.components.styles :as styles] (:require [status-im.ui.components.styles :as styles]
[status-im.ui.components.colors :as colors])) [status-im.ui.components.colors :as colors]))
@ -50,15 +50,6 @@
:padding-bottom 17 :padding-bottom 17
:margin-top 8}}) :margin-top 8}})
(defstyle form-title-extend-container
{:ios {:margin-top 16
:background-color colors/white}
:android {:margin-top 8
:background-color colors/gray-lighter}})
(def form-title-extend-button
{:padding 16})
(defstyle form-title (defstyle form-title
{:flex-shrink 1 {:flex-shrink 1
:ios {:color styles/text1-color :ios {:color styles/text1-color
@ -109,3 +100,51 @@
:color colors/blue :color colors/blue
:ios {:font-size 15} :ios {:font-size 15}
:android {:font-size 14}}) :android {:font-size 14}})
(defstyle logo-shaddow
{:ios {:shadowColor colors/black
:shadowOffset {:height 5}
:shadowRadius 10
:shadowOpacity 0.14}
:android {:elevation 2}})
(defn logo-container [size shadow?]
(merge
{:width size
:height size
:border-radius size
:background-color colors/blue
:align-items :center
:justify-content :center}
(when shadow?
logo-shaddow)))
(defn logo [icon-size]
{:color :white
:width icon-size
:height icon-size})
(defn bottom-button [disabled?]
{:flex-direction :row
:align-items :center
:opacity (if disabled? 0.4 1)})
(def bottom-button-label
{:font-size 15
:letter-spacing -0.2
:color colors/blue})
(defn button [style background?]
(merge
{:padding-vertical 12
:padding-horizontal 42
:border-radius 8}
style
(when background?
{:background-color (colors/alpha colors/blue 0.1)})))
(def button-label
{:font-size 15
:letter-spacing -0.2
:text-align :center
:color colors/blue})

View File

@ -77,7 +77,8 @@
:icons/network (slurp/slurp-svg "./resources/icons/network.svg") :icons/network (slurp/slurp-svg "./resources/icons/network.svg")
:icons/wnode (slurp/slurp-svg "./resources/icons/wnode.svg") :icons/wnode (slurp/slurp-svg "./resources/icons/wnode.svg")
:icons/refresh (slurp/slurp-svg "./resources/icons/refresh.svg") :icons/refresh (slurp/slurp-svg "./resources/icons/refresh.svg")
:icons/newchat (slurp/slurp-svg "./resources/icons/newchat.svg")}) :icons/newchat (slurp/slurp-svg "./resources/icons/newchat.svg")
:icons/logo (slurp/slurp-svg "./resources/icons/logo.svg")})
(defn normalize-property-name [n] (defn normalize-property-name [n]
(if (= n :icons/options) (if (= n :icons/options)
@ -86,13 +87,13 @@
(defn icon (defn icon
([name] (icon name nil)) ([name] (icon name nil))
([name {:keys [color container-style style accessibility-label] ([name {:keys [color container-style style accessibility-label width height]
:or {accessibility-label :icon}}] :or {accessibility-label :icon}}]
^{:key name} ^{:key name}
[react/view {:style container-style [react/view {:style container-style
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
(if-let [icon-fn (get icons (normalize-property-name name))] (if-let [icon-fn (get icons (normalize-property-name name))]
(icon-fn (let [icon-vec (icon-fn
(cond (cond
(keyword? color) (keyword? color)
(case color (case color
@ -106,5 +107,8 @@
(string? color) (string? color)
color color
:else :else
styles/icon-dark-color)) styles/icon-dark-color))]
(if width
(update icon-vec 1 assoc :width width :height height)
icon-vec))
(throw (js/Error. (str "Unknown icon: " name))))])) (throw (js/Error. (str "Unknown icon: " name))))]))

View File

@ -242,11 +242,10 @@
:wallet-send-transaction-request :wallet-send-transaction-request
:wallet-transaction-fee :wallet-transaction-fee
:contact-code) styles/color-blue4 :contact-code) styles/color-blue4
(:accounts
:login) styles/color-blue2
(:qr-viewer (:qr-viewer
:recipient-qr-code) "#2f3031" :recipient-qr-code) "#2f3031"
(:wallet-transactions-filter (:accounts :login
:wallet-transactions-filter
:contact-list-modal) styles/color-white :contact-list-modal) styles/color-white
:transparent)}) :transparent)})
children (cond-> children children (cond-> children

View File

@ -2,7 +2,7 @@
(:require [status-im.ui.components.react :as react] (:require [status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.styles :as styles])) [status-im.ui.components.status-bar.styles :as styles]))
(defn status-bar [{type :type}] (defn status-bar [{:keys [type flat?]}]
(let [[status-bar-style view-style] (let [[status-bar-style view-style]
(case type (case type
:main [styles/status-bar-main styles/view-main] :main [styles/status-bar-main styles/view-main]
@ -15,5 +15,5 @@
:wallet-tab [styles/status-bar-wallet-tab styles/view-wallet-tab] :wallet-tab [styles/status-bar-wallet-tab styles/view-wallet-tab]
[styles/status-bar-default styles/view-default])] [styles/status-bar-default styles/view-default])]
[react/view [react/view
[react/status-bar status-bar-style] [react/status-bar (cond-> status-bar-style flat? (assoc :elevation 0))]
[react/view {:style view-style}]])) [react/view {:style (cond-> view-style flat? (assoc :elevation 0))}]]))

View File

@ -99,10 +99,10 @@
:height 24}) :height 24})
(def icon-add (def icon-add
{:width 14 {:width 24
:height 14 :height 24
:color colors/blue :color colors/blue
:container-style {:background-color colors/blue-transparent :container-style {:background-color (colors/alpha colors/blue 0.12)
:border-radius 32 :border-radius 32
:width 32 :width 32
:height 32 :height 32

View File

@ -0,0 +1,27 @@
(ns status-im.ui.components.text-input.styles
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.ui.components.colors :as colors]))
(def label
{:font-size 14
:letter-spacing -0.2
:color colors/black})
(defn input-container [height]
{:padding 16
:justify-content :center
:margin-vertical 8
:height (or height 52)
:border-radius 8
:background-color colors/gray-lighter})
(def input
{:font-size 15
:letter-spacing -0.2
:color colors/black
:padding 0})
(def error
{:bottom-value -20
:color colors/red-light
:font-size 12})

View File

@ -0,0 +1,20 @@
(ns status-im.ui.components.text-input.view
(:require [status-im.ui.components.react :as react]
[status-im.ui.components.text-input.styles :as styles]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.tooltip.views :as tooltip]))
(defn text-input-with-label [{:keys [label error style height] :as props}]
[react/view
[react/text {:style styles/label}
label]
[react/view {:style (styles/input-container height)}
[react/text-input
(merge
{:style (merge styles/input style)
:placeholder-text-color colors/gray
:auto-focus true
:auto-capitalize :none}
(dissoc props :style :height))]]
(when error
[tooltip/tooltip error styles/error])])

View File

@ -1,32 +0,0 @@
(ns status-im.ui.components.text-input-with-label.animation
(:require [status-im.ui.components.animation :as animation]
[clojure.string :as string]))
(def anim-duration 200)
(defn animate-underline [underline-width to-line-width underline-height to-line-height]
(let [anim (animation/parallel [(animation/timing underline-width {:toValue to-line-width
:duration anim-duration})
(animation/timing underline-height {:toValue to-line-height
:duration anim-duration})])]
(animation/start anim)))
(defn text-input-on-focus [{:keys [underline-width underline-max-width* underline-height underline-max-height]}]
(animate-underline underline-width @underline-max-width* underline-height underline-max-height))
(defn text-input-on-blur [{:keys [underline-width underline-height]}]
(animate-underline underline-width 0 underline-height 1))
(defn animate-label [text {:keys [value* label-top label-font-size
label-top-top label-top-bottom label-font-size-top label-font-size-bottom]}]
(when (or (string/blank? text) (string/blank? @value*))
(let [was-blank? (string/blank? @value*)
anim (animation/parallel [(animation/timing label-top {:toValue (if was-blank?
label-top-top
label-top-bottom)
:duration anim-duration})
(animation/timing label-font-size {:toValue (if was-blank?
label-font-size-top
label-font-size-bottom)
:duration anim-duration})])]
(animation/start anim))))

View File

@ -1,68 +0,0 @@
(ns status-im.ui.components.text-input-with-label.styles
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.utils.platform :as platform]
[status-im.ui.components.styles :as common]))
(defstyle text-input
{:placeholder ""
:android {:padding-top 0
:padding-bottom 0
:padding-left 0
:margin-top 26
:margin-bottom 4
:font-size 16}
:ios {:margin-top 24
:margin-bottom 6
:font-size 17
:letter-spacing -0.2}})
(defstyle content-height
{:android {:height 24}
:ios {:height 26}})
(defstyle component-container
{:margin-left 16
:android {:min-height 76}
:ios {:min-height 78}})
(defnstyle label-animated-text [{:keys [label-top label-font-size]}]
{:position :absolute
:top label-top
:font-size label-font-size
:color common/color-gray4
:ios {:letter-spacing -0.2}})
(defstyle description-text
{:color common/color-gray4
:android {:margin-top 6
:font-size 12}
:ios {:margin-top 4
:font-size 14
:letter-spacing -0.2}})
(defstyle error-text
{:color common/color-red-2
:android {:margin-top 6
:font-size 12}
:ios {:margin-top 4
:font-size 14
:letter-spacing -0.2}})
(defn underline-blured [error]
{:background-color (if error common/color-red-2 common/color-light-gray2)
:align-items :center})
(defn underline-focused [underline-width underline-height error]
{:height underline-height
:width underline-width
:background-color (if error common/color-red-2 common/color-light-blue)})
(def label-top-top (if platform/ios? 6 6))
(def label-top-bottom (if platform/ios? 26 26))
(def label-font-size-top (if platform/ios? 14 12))
(def label-font-size-bottom (if platform/ios? 17 16))
(def underline-max-height (if platform/ios? 1 2))

View File

@ -1,72 +0,0 @@
(ns status-im.ui.components.text-input-with-label.view
(:require [reagent.core :as reagent]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.text-input-with-label.animation :as label-animation]
[status-im.ui.components.react :as react]
[status-im.ui.components.text-input-with-label.styles :as styles]
[clojure.string :as string]))
(defn get-init-props [{:keys [default-value]}]
(let [blank? (string/blank? default-value)]
{:underline-width (animation/create-value 0)
:underline-height (animation/create-value 1)
:label-top (animation/create-value (if blank?
styles/label-top-bottom
styles/label-top-top))
:label-font-size (animation/create-value (if blank?
styles/label-font-size-bottom
styles/label-font-size-top))
:label-top-top styles/label-top-top
:label-top-bottom styles/label-top-bottom
:label-font-size-top styles/label-font-size-top
:label-font-size-bottom styles/label-font-size-bottom
:underline-max-height styles/underline-max-height
:input-ref* (reagent/atom nil)
:value* (reagent/atom default-value)
:underline-max-width* (reagent/atom 0)}))
(defn get-width [event]
(.-width (.-layout (.-nativeEvent event))))
(defn text-input-on-change-text [text props]
(label-animation/animate-label text props)
(reset! (:value* props) text))
(defn text-input-handlers [{:keys [on-focus on-blur on-change-text on-change
on-submit-editing max-height ref]} props]
{:ref #(do
(reset! (:input-ref* props) %)
(when ref (ref %)))
:on-submit-editing #(do
(.blur @(:input-ref* props))
(when on-submit-editing (on-submit-editing)))
:on-focus #(do
(label-animation/text-input-on-focus props)
(when on-focus (on-focus)))
:on-blur #(do
(label-animation/text-input-on-blur props)
(when on-blur (on-blur)))
:on-change-text #(do
(text-input-on-change-text % props)
(when on-change-text (on-change-text %)))})
(defn text-input-with-label [options]
(let [props (get-init-props options)]
(fn [{:keys [label description error hide-underline? auto-expanding multiline] :as options}]
[react/view styles/component-container
[react/animated-text {:style (styles/label-animated-text props)} label]
[react/text-input (merge styles/text-input
(when-not (and auto-expanding multiline)
styles/content-height)
(dissoc options :label :description :error :auto-expanding :hide-underline?)
(text-input-handlers options props))]
(when-not hide-underline?
[react/view {:style (styles/underline-blured error)
:on-layout #(reset! (:underline-max-width* props) (get-width %))}
[react/animated-view {:style (styles/underline-focused (:underline-width props)
(:underline-height props)
error)}]])
(cond error
[react/text {:style styles/error-text} error]
description
[react/text {:style styles/description-text} description])])))

View File

@ -19,15 +19,13 @@
:android {:height 55} :android {:height 55}
:ios {:height 56}}) :ios {:height 56}})
(defnstyle toolbar-nav-actions-container (def toolbar-nav-actions-container
[actions]
{:flex-direction :row {:flex-direction :row
:margin-left 4}) :margin-left 4})
(defstyle toolbar-container (defstyle toolbar-container
{:flex 1 {:flex 1
:android {:padding-left 18} :align-items :center})
:ios {:align-items :center}})
(def toolbar-title-container (def toolbar-title-container
{:flex 1 {:flex 1
@ -38,15 +36,7 @@
{:color styles/text1-color {:color styles/text1-color
:letter-spacing -0.2 :letter-spacing -0.2
:font-size 17 :font-size 17
:ios {:text-align "center"}}) :text-align :center})
(defstyle toolbar-border-container
{:ios {:background-color styles/color-white}})
(defstyle toolbar-border
{:ios {:height 1
:background-color styles/color-gray5
:opacity 0.5}})
(def toolbar-actions (def toolbar-actions
{:flex 0 {:flex 0
@ -72,10 +62,6 @@
{:padding-vertical 16 {:padding-vertical 16
:padding-horizontal 12}) :padding-horizontal 12})
(def nav-item-text
{:padding-vertical 18
:padding-horizontal 16})
(defstyle item (defstyle item
{:ios {:margin-horizontal 12 {:ios {:margin-horizontal 12
:margin-vertical 16} :margin-vertical 16}

View File

@ -1,8 +1,6 @@
(ns status-im.ui.components.toolbar.view (ns status-im.ui.components.toolbar.view
(:require [reagent.core :as reagent] (:require [re-frame.core :as re-frame]
[re-frame.core :as re-frame]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
@ -110,21 +108,17 @@
(defn toolbar (defn toolbar
([props nav-item content-item] (toolbar props nav-item content-item [actions [{:image :blank}]])) ([props nav-item content-item] (toolbar props nav-item content-item [actions [{:image :blank}]]))
([{:keys [background-color style flat? title-centered?]} ([{:keys [background-color style flat?]}
nav-item nav-item
content-item content-item
action-items] action-items]
[react/view {:style (merge (styles/toolbar background-color flat?) style)} [react/view {:style (merge (styles/toolbar background-color flat?) style)}
;; On iOS title must be centered. Current solution is a workaround and eventually this will be sorted out using flex
(when (or title-centered? platform/ios?)
[react/view styles/ios-content-item [react/view styles/ios-content-item
content-item]) content-item]
(when nav-item (when nav-item
[react/view {:style (styles/toolbar-nav-actions-container 0)} [react/view {:style styles/toolbar-nav-actions-container}
nav-item]) nav-item])
(if (or title-centered? platform/ios?)
[react/view components.styles/flex] [react/view components.styles/flex]
content-item)
action-items])) action-items]))
(defn simple-toolbar (defn simple-toolbar

View File

@ -0,0 +1,12 @@
(ns status-im.ui.components.tooltip.animations
(:require [status-im.ui.components.animation :as animation]))
(defn animate-tooltip [bottom-value bottom-anim-value opacity-value]
(fn []
(animation/start
(animation/parallel
[(animation/timing opacity-value {:toValue 1
:duration 500})
(animation/timing bottom-anim-value {:toValue (- bottom-value 10)
:easing (.bezier (animation/easing) 0.685, 0.000, 0.025, 1.185)
:duration 500})]))))

View File

@ -0,0 +1,31 @@
(ns status-im.ui.components.tooltip.styles
(:require [status-im.ui.components.styles :as styles]))
(def tooltip-container
{:position :absolute
:align-items :center
:left 0
:right 0
:top 0})
(defn tooltip-animated [bottom-value opacity-value]
{:position :absolute
:align-items :center
:left 0
:right 0
:bottom bottom-value
:opacity opacity-value})
(defn tooltip-text-container [color]
{:padding-horizontal 16
:padding-vertical 9
:background-color color
:border-radius 8})
(defn tooltip-text [font-size]
{:color styles/color-red-2
:font-size font-size})
(def tooltip-triangle
{:width 16
:height 8})

View File

@ -0,0 +1,17 @@
(ns status-im.ui.components.tooltip.views
(:require-macros [status-im.utils.views :as views])
(:require [status-im.ui.components.animation :as animation]
[status-im.ui.components.tooltip.animations :as animations]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.tooltip.styles :as styles]))
(views/defview tooltip [label & [{:keys [bottom-value color font-size] :or {bottom-value -30 color :white font-size 15}}]]
(views/letsubs [bottom-anim-value (animation/create-value bottom-value)
opacity-value (animation/create-value 0)]
{:component-did-mount (animations/animate-tooltip bottom-value bottom-anim-value opacity-value)}
[react/view styles/tooltip-container
[react/animated-view {:style (styles/tooltip-animated bottom-value opacity-value)}
[react/view (styles/tooltip-text-container color)
[react/text {:style (styles/tooltip-text font-size)} label]]
[vector-icons/icon :icons/tooltip-triangle {:color color :style styles/tooltip-triangle}]]]))

View File

@ -0,0 +1,9 @@
(ns status-im.ui.screens.accounts.create.navigation
(:require [status-im.ui.screens.navigation :as nav]))
(defmethod nav/preload-data! :create-account
[db]
(update db :accounts/create
#(-> %
(assoc :step :enter-password)
(dissoc :password :password-confirm :name :error))))

View File

@ -0,0 +1,58 @@
(ns status-im.ui.screens.accounts.create.styles
(:require [status-im.ui.components.colors :as colors]))
(def create-account-view
{:flex 1
:background-color colors/white})
(def account-creating-view
{:flex 1
:padding-horizontal 14})
(def account-creating-logo-container
{:margin-top 37
:align-items :center})
(def account-creating-logo
{:size 82
:icon-size 34})
(def account-creating-indicatior
{:flex 1
:align-items :center
:justify-content :center
:margin-bottom 100})
(def account-creating-text
{:font-size 14
:line-height 21
:letter-spacing -0.2
:text-align :center
:color colors/black
:margin-top 16})
(def logo-container
{:position :absolute
:top 37
:left 0
:right 0
:align-items :center})
(def logo
{:size 82
:icon-size 34})
(def input-container
{:margin-horizontal 16
:margin-top 105})
(def input-description
{:font-size 14
:letter-spacing -0.2
:color colors/gray
:line-height 21})
(def bottom-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})

View File

@ -0,0 +1,85 @@
(ns status-im.ui.screens.accounts.create.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.react :as react]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.toolbar.actions :as actions]
[status-im.ui.components.react :as components]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.text-input.view :as text-input]
[status-im.ui.screens.accounts.create.styles :as styles]))
(def steps
{:enter-password {:input-key :password
:input-label (i18n/label :t/password)
:input-placeholder (i18n/label :t/password-placeholder)
:input-description (i18n/label :t/password-description)}
:confirm-password {:input-key :password-confirm
:input-label (i18n/label :t/confirm)
:input-placeholder (i18n/label :t/password-placeholder2)
:input-description (i18n/label :t/password-description)}
:account-creating nil
:enter-name {:input-key :name
:input-label (i18n/label :t/name)
:input-placeholder (i18n/label :t/name-placeholder)
:input-description (i18n/label :t/name-description)}})
(defn next-step [step password password-confirm]
(case step
:enter-password (re-frame/dispatch [:set-in [:accounts/create :step] :confirm-password])
:confirm-password (if (= password password-confirm)
(re-frame/dispatch [:create-account])
(re-frame/dispatch [:set-in [:accounts/create :error] (i18n/label :t/password_error1)]))
:enter-name (re-frame/dispatch [:account-set-name])))
(defn step-back [step]
(case step
:enter-password (re-frame/dispatch [:navigate-back])
:confirm-password (re-frame/dispatch [:reset-account-creation])))
(defview input [step error]
[text-input/text-input-with-label
{:label (get-in steps [step :input-label])
:placeholder (get-in steps [step :input-placeholder])
:on-change-text #(re-frame/dispatch [:set-in [:accounts/create (get-in steps [step :input-key])] %])
:secure-text-entry (boolean (#{:enter-password :confirm-password} step))
:error error}])
(defview create-account []
(letsubs [step [:get-in [:accounts/create :step]]
next-enabled? [:get-account-creation-next-enabled?]
error [:get-in [:accounts/create :error]]
password [:get-in [:accounts/create :password]]
password-confirm [:get-in [:accounts/create :password-confirm]]]
[react/keyboard-avoiding-view {:style styles/create-account-view}
[status-bar/status-bar {:flat? true}]
(when (= :account-creating step)
[react/view styles/account-creating-view
[react/view styles/account-creating-logo-container
[components.common/logo styles/account-creating-logo]]
[react/view {:style styles/account-creating-indicatior}
[components/activity-indicator {:animating true}]
[react/text {:style styles/account-creating-text}
(i18n/label :t/creating-your-account)]]])
(when (#{:enter-password :confirm-password :enter-name} step)
[react/view components.styles/flex
[toolbar/toolbar {:flat? true} (when (#{:enter-password :confirm-password} step)
(toolbar/nav-button (actions/back #(step-back step)))) nil]
[react/view {:style styles/logo-container}
[components.common/logo styles/logo]]
^{:key (str "step" step)}
[react/view components.styles/flex
[react/view {:style styles/input-container}
[input step error]
[react/text {:style styles/input-description}
(get-in steps [step :input-description])]]
[react/view {:style components.styles/flex}]
[react/view {:style styles/bottom-container}
[react/view {:style components.styles/flex}]
[components.common/bottom-button
{:forward? true
:disabled? (not next-enabled?)
:on-press #(next-step step password password-confirm)}]]]])]))

View File

@ -2,7 +2,13 @@
(:require-macros [status-im.utils.db :refer [allowed-keys]]) (:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]
status-im.utils.db status-im.utils.db
status-im.ui.screens.network-settings.db)) status-im.ui.screens.network-settings.db
[status-im.constants :as const]))
(defn valid-length? [password]
(>= (count password) const/min-password-length))
(spec/def ::password (spec/and :global/not-empty-string valid-length?))
(spec/def :account/address :global/address) (spec/def :account/address :global/address)
(spec/def :account/name :global/not-empty-string) (spec/def :account/name :global/not-empty-string)
@ -11,6 +17,7 @@
(spec/def :account/email nil?) (spec/def :account/email nil?)
(spec/def :account/signed-up? (spec/nilable boolean?)) (spec/def :account/signed-up? (spec/nilable boolean?))
(spec/def :account/last-updated (spec/nilable int?)) (spec/def :account/last-updated (spec/nilable int?))
(spec/def :account/last-sign-in (spec/nilable int?))
(spec/def :account/updates-private-key :global/not-empty-string) (spec/def :account/updates-private-key :global/not-empty-string)
(spec/def :account/updates-public-key :global/not-empty-string) (spec/def :account/updates-public-key :global/not-empty-string)
(spec/def :account/photo-path (spec/nilable string?)) (spec/def :account/photo-path (spec/nilable string?))
@ -21,6 +28,7 @@
(spec/def :account/wnode (spec/nilable string?)) (spec/def :account/wnode (spec/nilable string?))
(spec/def :account/settings (spec/nilable (spec/map-of keyword? any?))) (spec/def :account/settings (spec/nilable (spec/map-of keyword? any?)))
(spec/def :account/signing-phrase :global/not-empty-string) (spec/def :account/signing-phrase :global/not-empty-string)
(spec/def :account/sharing-usage-data? (spec/nilable boolean?))
(spec/def :accounts/account (allowed-keys (spec/def :accounts/account (allowed-keys
:req-un [:account/name :account/address :account/public-key :req-un [:account/name :account/address :account/public-key
@ -28,16 +36,16 @@
:opt-un [:account/debug? :account/status :account/last-updated :opt-un [:account/debug? :account/status :account/last-updated
:account/updates-private-key :account/updates-public-key :account/updates-private-key :account/updates-public-key
:account/email :account/signed-up? :account/network :account/email :account/signed-up? :account/network
:account/networks :account/settings :account/wnode])) :account/networks :account/settings :account/wnode
:account/last-sign-in :account/sharing-usage-data?]))
(spec/def :accounts/accounts (spec/nilable (spec/map-of :account/address :accounts/account))) (spec/def :accounts/accounts (spec/nilable (spec/map-of :account/address :accounts/account)))
;;true during creating new account
(spec/def :accounts/account-creation? (spec/nilable boolean?))
;;true during login just created account
(spec/def :accounts/creating-account? (spec/nilable boolean?))
;;id of logged in account ;;id of logged in account
(spec/def :accounts/current-account-id (spec/nilable string?)) (spec/def :accounts/current-account-id (spec/nilable string?))
;;used during creating account
(spec/def :accounts/create (spec/nilable map?))
;;used during recovering account ;;used during recovering account
(spec/def :accounts/recover (spec/nilable map?)) (spec/def :accounts/recover (spec/nilable map?))
;;used during logging ;;used during logging

View File

@ -13,17 +13,8 @@
[status-im.ui.screens.accounts.statuses :as statuses] [status-im.ui.screens.accounts.statuses :as statuses]
[status-im.utils.signing-phrase.core :as signing-phrase] [status-im.utils.signing-phrase.core :as signing-phrase]
[status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.utils.hex :as utils.hex])) [status-im.utils.hex :as utils.hex]
status-im.ui.screens.accounts.create.navigation))
;;;; Helper fns
(defn create-account
"Takes db and password, creates map of effects describing account creation"
[db password]
{:db (assoc db :accounts/creating-account? true)
::create-account password
;; TODO(janherich): get rid of this shitty delayed dispatch once sending commands/msgs is refactored
:dispatch-later [{:ms 400 :dispatch [:account-generation-message]}]})
;;;; COFX ;;;; COFX
@ -90,6 +81,12 @@
:private updates-private-key}}}})))) :private updates-private-key}}}}))))
;;;; Handlers ;;;; Handlers
(handlers/register-handler-fx
:create-account
(fn [{{:accounts/keys [create] :as db} :db}]
{:db (update db :accounts/create assoc :step :account-creating :error nil)
::create-account (:password create)}))
(defn add-account (defn add-account
"Takes db and new account, creates map of effects describing adding account to database and realm" "Takes db and new account, creates map of effects describing adding account to database and realm"
[{:keys [network inbox/wnode] :networks/keys [networks] :as db} {:keys [address] :as account}] [{:keys [network inbox/wnode] :networks/keys [networks] :as db} {:keys [address] :as account}]
@ -126,15 +123,7 @@
(log/debug "account-created") (log/debug "account-created")
(when-not (str/blank? pubkey) (when-not (str/blank? pubkey)
(-> (add-account db account) (-> (add-account db account)
(assoc :dispatch-n [[:show-mnemonic mnemonic signing-phrase] (assoc :dispatch [:login-account normalized-address password true]))))))
[:login-account normalized-address password true]]))))))
(handlers/register-handler-fx
:create-new-account-handler
(fn [_ _]
{:dispatch-n [[:initialize-db]
[:load-accounts]
[:check-console-chat true]]}))
(handlers/register-handler-fx (handlers/register-handler-fx
:load-accounts :load-accounts
@ -204,3 +193,20 @@
;; TODO(janherich): this is very strange and misleading, need to figure out why it'd necessary to update ;; TODO(janherich): this is very strange and misleading, need to figure out why it'd necessary to update
;; account with network update when last update was more then week ago ;; account with network update when last update was more then week ago
(account-update {:db db} nil))))) (account-update {:db db} nil)))))
(handlers/register-handler-fx
:account-set-name
(fn [{{:accounts/keys [create] :as db} :db} _]
(-> {:db (assoc-in db [:accounts/create :show-welcome?] true)
:dispatch [:navigate-to-clean :usage-data]}
(account-update {:name (:name create)}))))
(handlers/register-handler-fx
:update-sign-in-time
(fn [{db :db now :now} _]
(account-update {:db db} {:last-sign-in now})))
(handlers/register-handler-fx
:reset-account-creation
(fn [{db :db} _]
{:db (update db :accounts/create assoc :step :enter-password :password nil :password-confirm nil :error nil)}))

View File

@ -3,11 +3,9 @@
[re-frame.core :refer [dispatch reg-fx]] [re-frame.core :refer [dispatch reg-fx]]
[status-im.utils.handlers :refer [register-handler-db register-handler-fx]] [status-im.utils.handlers :refer [register-handler-db register-handler-fx]]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.chat.console :as console-chat]
[status-im.utils.types :refer [json->clj]] [status-im.utils.types :refer [json->clj]]
[status-im.data-store.core :as data-store] [status-im.data-store.core :as data-store]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.constants :refer [console-chat-id]]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.constants :as constants])) [status-im.constants :as constants]))
@ -16,7 +14,6 @@
(reg-fx ::stop-node (fn [] (status/stop-node))) (reg-fx ::stop-node (fn [] (status/stop-node)))
(reg-fx (reg-fx
::login ::login
(fn [[address password]] (fn [[address password]]
@ -94,11 +91,10 @@
(register-handler-fx (register-handler-fx
:login-account :login-account
(fn [{{:keys [network status-node-started?] :as db} :db} (fn [{{:keys [network status-node-started?] :as db} :db}
[_ address password account-creation?]] [_ address password]]
(let [{account-network :network} (get-network-by-address db address) (let [{account-network :network} (get-network-by-address db address)
wnode (get-wnode-by-address db address) wnode (get-wnode-by-address db address)
db' (-> db db' (-> db
(assoc :accounts/account-creation? account-creation?)
(assoc :inbox/wnode wnode) (assoc :inbox/wnode wnode)
(assoc-in [:accounts/login :processing] true)) (assoc-in [:accounts/login :processing] true))
wrap-fn (cond (not status-node-started?) wrap-fn (cond (not status-node-started?)
@ -113,32 +109,27 @@
(register-handler-fx (register-handler-fx
:login-handler :login-handler
(fn [{{:accounts/keys [account-creation?] :as db} :db} [_ login-result address]] (fn [{db :db} [_ login-result address]]
(let [data (json->clj login-result) (let [data (json->clj login-result)
error (:error data) error (:error data)
success (zero? (count error)) success (zero? (count error))
db' (assoc-in db [:accounts/login :processing] false)] db' (assoc-in db [:accounts/login :processing] false)]
(log/debug "Logging result: " login-result) (if success
(merge {:db db'
{:db (if success db' (assoc-in db' [:accounts/login :error] error))} ::clear-web-data nil
(when success ::change-account [address]}
(log/debug "Logged in" (when account-creation? " new account") ":" address) {:db (assoc-in db' [:accounts/login :error] error)}))))
{::clear-web-data nil
::change-account [address account-creation?]})))))
(register-handler-fx (register-handler-fx
:change-account-handler :change-account-handler
(fn [{db :db} [_ error address new-account?]] (fn [{{:keys [view-id] :as db} :db} [_ error address]]
(let [recover-in-progress? (:accounts/recover db)]
(if (nil? error) (if (nil? error)
{:db (dissoc db :accounts/login) {:db (cond-> (dissoc db :accounts/login)
:dispatch-n [[:stop-debugging] (= view-id :create-account)
[:initialize-account (assoc-in [:accounts/create :step] :enter-name))
address :dispatch-n (concat
(when (or new-account? recover-in-progress?) [[:stop-debugging]
[[:chat-received-message/add console-chat/shake-your-phone-message]])] [:initialize-account address]]
[:navigate-to-clean :home] (when (not= view-id :create-account)
(if new-account? [[:navigate-to-clean :home]]))}
[:navigate-to-chat console-chat-id] (log/debug "Error changing acount: " error))))
[:navigate-to :home])]}
(log/debug "Error changing acount: " error)))))

View File

@ -1,46 +1,44 @@
(ns status-im.ui.screens.accounts.login.styles (ns status-im.ui.screens.accounts.login.styles
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]) (:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
(:require [status-im.ui.components.styles :as st])) (:require [status-im.ui.components.styles :as st]
[status-im.ui.components.colors :as colors]))
(defstyle login-view (defstyle login-view
{:flex 1 {:flex 1
:ios {:margin-top 10
:margin-bottom 10}
:android {:margin-top 16
:margin-bottom 16}
:margin-horizontal 16}) :margin-horizontal 16})
(defstyle login-badge-container (defstyle login-badge-container
{:background-color :white {:margin-top 24})
:ios {:padding-top 16
:height 150}
:android {:border-radius 4
:padding-top 12
:height 144}})
(defstyle sign-it-text
{:color :white
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 16}})
(def sign-it-disabled-text
(merge sign-it-text
{:color st/color-gray2}))
(def sign-in-button
{:background-color st/color-blue3
:align-items :center
:justify-content :center
:height 52
:border-radius 8})
(def processing-view (def processing-view
{:position :absolute {:flex 1
:top 0
:bottom 0
:right 0
:left 0
:align-items :center :align-items :center
:justify-content :center :justify-content :center})
:background-color (str st/color-black "1A")})
(def sign-you-in
{:margin-top 16
:font-size 13
:letter-spacing -0.2
:color colors/text-light-gray})
(def bottom-button-container
{:flex-direction :row
:margin-horizontal 12
:margin-vertical 15
:align-items :center})
(def login-badge
{:align-items :center})
(def login-badge-image
{:width 56
:height 56
:border-radius 28})
(def login-badge-name
{:font-size 15
:color colors/text-light-gray
:margin-top 8})
(def password-container
{:margin-top 24})

View File

@ -1,28 +1,30 @@
(ns status-im.ui.screens.accounts.login.views (ns status-im.ui.screens.accounts.login.views
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :refer [dispatch dispatch-sync]]
[status-im.ui.screens.accounts.styles :as ast] [status-im.ui.screens.accounts.styles :as ast]
[status-im.ui.screens.accounts.views :refer [account-badge]] [status-im.ui.components.text-input.view :as text-input]
[status-im.ui.components.text-input-with-label.view :refer [text-input-with-label]] [status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.status-bar.view :refer [status-bar]]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.toolbar.actions :as act] [status-im.ui.components.toolbar.actions :as act]
[status-im.ui.screens.accounts.login.styles :as st] [status-im.ui.screens.accounts.login.styles :as styles]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.react :as components])) [status-im.ui.components.react :as components]
[status-im.ui.components.common.common :as components.common]
[re-frame.core :as re-frame]
[cljs.spec.alpha :as spec]
[status-im.ui.screens.accounts.db :as db]))
(defn login-toolbar [] (defn login-toolbar [can-navigate-back?]
[toolbar/toolbar {:background-color :transparent} [toolbar/toolbar
[toolbar/nav-button (act/back-white #(dispatch [:navigate-back]))] nil
[toolbar/content-title {:color :white} (i18n/label :t/sign-in-to-status)]]) (when can-navigate-back?
[toolbar/nav-button act/default-back])
(def password-text-input (atom nil)) [toolbar/content-title (i18n/label :t/sign-in-to-status)]])
(defn login-account [password-text-input address password] (defn login-account [password-text-input address password]
(.blur @password-text-input) (.blur password-text-input)
(dispatch [:login-account address password])) (re-frame/dispatch [:login-account address password]))
(defn- error-key [error] (defn- error-key [error]
;; TODO Improve selection logic when status-go provide an error code ;; TODO Improve selection logic when status-go provide an error code
@ -37,31 +39,53 @@
:else :else
:t/unknown-status-go-error)) :t/unknown-status-go-error))
(defn account-login-badge [photo-path name]
[react/view styles/login-badge
[react/image {:source {:uri (if (string/blank? photo-path) :avatar photo-path)}
:style styles/login-badge-image}]
[react/view
[react/text {:style styles/login-badge-name
:numberOfLines 1}
name]]])
(defview login [] (defview login []
(letsubs [{:keys [address photo-path name password error processing]} [:get :accounts/login]] (letsubs [{:keys [address photo-path name password error processing]} [:get :accounts/login]
[react/view ast/accounts-container can-navigate-back? [:can-navigate-back?]
[status-bar {:type :transparent}] password-text-input (atom nil)]
[login-toolbar] [react/keyboard-avoiding-view {:style ast/accounts-view}
[react/view st/login-view [status-bar/status-bar]
[react/view st/login-badge-container [login-toolbar can-navigate-back?]
[account-badge address photo-path name] [components.common/separator]
[react/view {:height 8}] [react/view styles/login-view
[text-input-with-label {:ref #(reset! password-text-input %) [react/view styles/login-badge-container
:label (i18n/label :t/password) [account-login-badge photo-path name]
:auto-capitalize :none [react/view styles/password-container
:hide-underline? true [text-input/text-input-with-label
{:label (i18n/label :t/password)
:placeholder (i18n/label :t/password)
:ref #(reset! password-text-input %)
:auto-focus can-navigate-back? ;;this needed because keyboard overlays testfairy alert
:on-submit-editing #(login-account @password-text-input address password)
:on-change-text #(do :on-change-text #(do
(dispatch [:set-in [:accounts/login :password] %]) (re-frame/dispatch [:set-in [:accounts/login :password] %])
(dispatch [:set-in [:accounts/login :error] ""])) (re-frame/dispatch [:set-in [:accounts/login :error] ""]))
:on-submit-editing #(login-account password-text-input address password)
:auto-focus true
:secure-text-entry true :secure-text-entry true
:error (when (pos? (count error)) (i18n/label (error-key error)))}]] :error (when (pos? (count error)) (i18n/label (error-key error)))}]]]]
(let [enabled? (pos? (count password))] [react/view styles/processing-view
[react/view {:margin-top 16}
[react/touchable-highlight (if enabled? {:on-press #(login-account password-text-input address password)})
[react/view st/sign-in-button
[react/text {:style (if enabled? st/sign-it-text st/sign-it-disabled-text)} (i18n/label :t/sign-in)]]]])]
(when processing (when processing
[react/view st/processing-view [components/activity-indicator {:animating true}])
[components/activity-indicator {:animating true}]])])) (when processing
[react/text {:style styles/sign-you-in}
(i18n/label :t/sign-you-in)])]
(when-not processing
[react/view {:style styles/bottom-button-container}
(when-not can-navigate-back?
[components.common/bottom-button
{:label (i18n/label :t/other-accounts)
:on-press #(re-frame/dispatch [:navigate-to-clean :accounts])}])
[react/view {:style {:flex 1}}]
[components.common/bottom-button
{:forward? true
:label (i18n/label :t/sign-in)
:disabled? (not (spec/valid? ::db/password password))
:on-press #(login-account @password-text-input address password)}]])]))

View File

@ -1,10 +1,4 @@
(ns status-im.ui.screens.accounts.recover.db (ns status-im.ui.screens.accounts.recover.db
(:require [cljs.spec.alpha :as spec] (:require [cljs.spec.alpha :as spec]))
[status-im.constants :as const]
status-im.utils.db))
(defn valid-length? [password]
(>= (count password) const/min-password-length))
(spec/def ::passphrase :global/not-empty-string) (spec/def ::passphrase :global/not-empty-string)
(spec/def ::password (spec/and :global/not-empty-string valid-length?))

View File

@ -1,55 +1,52 @@
(ns status-im.ui.screens.accounts.recover.events (ns status-im.ui.screens.accounts.recover.events
(:require (:require
status-im.ui.screens.accounts.recover.navigation status-im.ui.screens.accounts.recover.navigation
[re-frame.core :as re-frame]
[re-frame.core :refer [reg-fx inject-cofx dispatch]]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.ui.screens.accounts.events :as accounts-events] [status-im.ui.screens.accounts.events :as accounts-events]
[status-im.utils.types :refer [json->clj]] [status-im.utils.types :as types]
[status-im.utils.identicon :refer [identicon]] [status-im.utils.identicon :as identicon]
[taoensso.timbre :as log] [clojure.string :as string]
[clojure.string :as str] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers :refer [register-handler-fx]] [status-im.utils.gfycat.core :as gfycat]
[status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.utils.signing-phrase.core :as signing-phrase] [status-im.utils.signing-phrase.core :as signing-phrase]
[status-im.utils.hex :as utils.hex])) [status-im.utils.hex :as utils.hex]))
;;;; FX ;;;; FX
(reg-fx (re-frame/reg-fx
::recover-account-fx ::recover-account-fx
(fn [[passphrase password]] (fn [[passphrase password]]
(status/recover-account (status/recover-account
(str/trim passphrase) (string/trim passphrase)
password password
#(dispatch [:account-recovered %])))) #(re-frame/dispatch [:account-recovered % password]))))
;;;; Handlers ;;;; Handlers
(register-handler-fx (handlers/register-handler-fx
:account-recovered :account-recovered
[(inject-cofx :get-new-keypair!)] [(re-frame/inject-cofx :get-new-keypair!)]
(fn [{:keys [db keypair]} [_ result]] (fn [{:keys [db keypair]} [_ result password]]
(let [data (json->clj result) (let [data (types/json->clj result)
public-key (:pubkey data) public-key (:pubkey data)
address (-> data :address utils.hex/normalize-hex) address (-> data :address utils.hex/normalize-hex)
phrase (signing-phrase/generate) phrase (signing-phrase/generate)
{:keys [public private]} keypair {:keys [public private]} keypair
account {:public-key public-key account {:public-key public-key
:address address :address address
:name (generate-gfy public-key) :name (gfycat/generate-gfy public-key)
:photo-path (identicon public-key) :photo-path (identicon/identicon public-key)
:updates-public-key public :updates-public-key public
:updates-private-key private :updates-private-key private
:signed-up? true :signed-up? true
:signing-phrase phrase}] :signing-phrase phrase}]
(log/debug "account-recovered") (when-not (string/blank? public-key)
(when-not (str/blank? public-key)
(-> db (-> db
(accounts-events/add-account account) (accounts-events/add-account account)
(assoc :dispatch [:navigate-to-clean :accounts])))))) (assoc :dispatch [:login-account address password]))))))
(register-handler-fx (handlers/register-handler-fx
:recover-account :recover-account
(fn [_ [_ passphrase password]] (fn [_ [_ passphrase password]]
{::recover-account-fx [passphrase password]})) {::recover-account-fx [passphrase password]}))

View File

@ -1,10 +1,11 @@
(ns status-im.ui.screens.accounts.recover.styles (ns status-im.ui.screens.accounts.recover.styles
(:require [status-im.ui.components.styles :as common] (:require [status-im.ui.components.colors :as colors]))
[status-im.utils.platform :refer [ios?]]))
(def screen-container (def screen-container
{:flex 1 {:flex 1
:background-color common/color-white}) :background-color colors/white})
(def passphrase-input-max-height (def bottom-button-container
(if ios? 78 72)) {:flex-direction :row
:margin-horizontal 12
:margin-vertical 15})

View File

@ -1,63 +1,59 @@
(ns status-im.ui.screens.accounts.recover.views (ns status-im.ui.screens.accounts.recover.views
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :refer [dispatch]] (:require [re-frame.core :as re-frame]
[status-im.ui.components.text-input-with-label.view :refer [text-input-with-label]] [status-im.ui.components.text-input.view :as text-input]
[status-im.ui.components.react :refer [view [status-im.ui.components.react :as react]
text [status-im.ui.components.status-bar.view :as status-bar]
image
keyboard-avoiding-view
touchable-highlight]]
[status-im.ui.components.sticky-button :refer [sticky-button]]
[status-im.ui.components.status-bar.view :refer [status-bar]]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.toolbar.actions :as act]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.screens.accounts.recover.styles :as st] [status-im.ui.screens.accounts.recover.styles :as styles]
[status-im.ui.screens.accounts.recover.db :as v] [status-im.ui.screens.accounts.recover.db :as recover.db]
[status-im.ui.screens.accounts.db :as db]
[cljs.spec.alpha :as spec] [cljs.spec.alpha :as spec]
[clojure.string :as str])) [status-im.ui.components.common.common :as components.common]))
(defview passphrase-input [passphrase] (defview passphrase-input [passphrase]
(letsubs [error [:get-in [:accounts/recover :passphrase-error]]] (letsubs [error [:get-in [:accounts/recover :passphrase-error]]]
[view {:margin-top 10} [text-input/text-input-with-label
[text-input-with-label {:label (i18n/label :t/passphrase) {:style {:flex 1}
:description (i18n/label :t/twelve-words-in-correct-order) :height 92
:label (i18n/label :t/passphrase)
:placeholder (i18n/label :t/enter-12-words)
:multiline true :multiline true
:auto-expanding true
:max-height st/passphrase-input-max-height
:default-value passphrase :default-value passphrase
:auto-capitalize :none :on-change-text #(re-frame/dispatch [:set-in [:accounts/recover :passphrase] %])
:on-change-text #(dispatch [:set-in [:accounts/recover :passphrase] %]) :error error}]))
:error error}]]))
(defview password-input [password] (defview password-input [password]
(letsubs [error [:get-in [:accounts/recover :password-error]]] (letsubs [error [:get-in [:accounts/recover :password-error]]]
[view {:margin-top 10} [react/view {:margin-top 10}
[text-input-with-label {:label (i18n/label :t/password) [text-input/text-input-with-label
{:label (i18n/label :t/password)
:placeholder (i18n/label :t/enter-password)
:default-value password :default-value password
:auto-capitalize :none :auto-focus false
:on-change-text #(dispatch [:set-in [:accounts/recover :password] %]) :on-change-text #(re-frame/dispatch [:set-in [:accounts/recover :password] %])
:secure-text-entry true :secure-text-entry true
:error error}]])) :error error}]]))
(defview recover [& [modal?]] (defview recover []
(letsubs [{:keys [passphrase password]} [:get :accounts/recover]] (letsubs [{:keys [passphrase password]} [:get :accounts/recover]]
(let [valid-form? (and (let [valid-form? (and
(spec/valid? ::v/passphrase passphrase) (spec/valid? ::recover.db/passphrase passphrase)
(spec/valid? ::v/password password))] (spec/valid? ::db/password password))]
[keyboard-avoiding-view {:style st/screen-container} [react/keyboard-avoiding-view {:style styles/screen-container}
[status-bar] [status-bar/status-bar]
[toolbar/toolbar {:modal? modal?} toolbar/default-nav-back [toolbar/toolbar nil toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/recover-access)]] [toolbar/content-title (i18n/label :t/sign-in-to-another)]]
[components.common/separator]
[react/view {:margin 16}
[passphrase-input (or passphrase "")] [passphrase-input (or passphrase "")]
[password-input (or password "")] [password-input (or password "")]]
[view {:flex 1}] [react/view {:flex 1}]
(when valid-form? [react/view {:style styles/bottom-button-container}
[sticky-button [react/view {:style {:flex 1}}]
(i18n/label :t/recover-access) [components.common/bottom-button
#(do {:forward? true
(when modal? (dispatch [:navigate-back])) :label (i18n/label :t/sign-in)
(dispatch [:recover-account passphrase password]))])]))) :disabled? (not valid-form?)
:on-press #(re-frame/dispatch [:recover-account passphrase password])}]]])))
(defview recover-modal []
[recover true])

View File

@ -1,10 +1,16 @@
(ns status-im.ui.screens.accounts.styles (ns status-im.ui.screens.accounts.styles
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]) (:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
(:require [status-im.ui.components.styles :as common])) (:require [status-im.ui.components.styles :as common]
[status-im.ui.components.colors :as colors]))
(def accounts-view
{:flex 1
:background-color colors/white})
(def accounts-container (def accounts-container
{:flex 1 {:flex 1
:background-color common/color-blue2}) :padding-horizontal 16
:background-color colors/gray-lighter})
(def bottom-actions-container (def bottom-actions-container
{:margin-bottom 16}) {:margin-bottom 16})
@ -14,54 +20,40 @@
:width 40 :width 40
:border-radius 20}) :border-radius 20})
(defstyle account-title-conatiner
{:justify-content :center
:align-items :center
:ios {:height 56}
:android {:height 55}})
(defstyle account-title-text (defstyle account-title-text
{:color :white {:color :black
:font-size 17 :font-size 17
:ios {:letter-spacing -0.2}}) :ios {:letter-spacing -0.2}})
(defstyle accounts-list-container (defstyle accounts-list-container
{:flex 1 {:flex 1
:margin-horizontal 16 :margin-top 16
:ios {:margin-top 10 :margin-bottom 16})
:margin-bottom 10}
:android {:margin-top 16
:margin-bottom 16}})
(def accounts-action-button
{:label-style {:color :white}
:cyrcle-color "#ffffff33"})
(def accounts-separator
{:background-color "#7482eb"
:opacity 1
:margin-left 72})
(def accounts-separator-wrapper
{:background-color common/color-blue2})
(defstyle account-view (defstyle account-view
{:background-color :white {:background-color :white
:justify-content :center :flex-direction :row
:align-items :center
:padding-horizontal 16
:height 64 :height 64
:border-radius 8}) :border-radius 8})
(def account-badge
{:flex-direction :row
:align-items :center
:padding-horizontal 16})
(def account-badge-text-view (def account-badge-text-view
{:margin-left 16 {:margin-left 16
:margin-right 21
:flex-shrink 1}) :flex-shrink 1})
(defstyle account-badge-text (def account-badge-text
{:ios {:font-size 17 {:font-size 17
:letter-spacing -0.2} :letter-spacing -0.2
:android {:font-size 16 :color common/color-black})
:color common/color-black}})
(def account-badge-pub-key-text
{:font-size 14
:letter-spacing -0.2
:color colors/gray
:margin-top 4})
(def bottom-button-container
{:margin-top 14
:margin-bottom 6})

View File

@ -1,5 +1,8 @@
(ns status-im.ui.screens.accounts.subs (ns status-im.ui.screens.accounts.subs
(:require [re-frame.core :refer [reg-sub subscribe]])) (:require [re-frame.core :refer [reg-sub subscribe]]
[clojure.string :as string]
[status-im.ui.screens.accounts.db :as db]
[cljs.spec.alpha :as spec]))
(reg-sub :get-current-public-key (reg-sub :get-current-public-key
(fn [db] (fn [db]
@ -18,3 +21,11 @@
:<- [:get-accounts] :<- [:get-accounts]
(fn [[account-id accounts]] (fn [[account-id accounts]]
(some-> accounts (get account-id)))) (some-> accounts (get account-id))))
(reg-sub
:get-account-creation-next-enabled?
(fn [{:accounts/keys [create]}]
(let [{:keys [step password password-confirm name]} create]
(or (and password (= :enter-password step) (spec/valid? ::db/password password))
(and password-confirm (= :confirm-password step) (spec/valid? ::db/password password-confirm))
(and name (= :enter-name step) (not (string/blank? name)))))))

View File

@ -1,56 +1,48 @@
(ns status-im.ui.screens.accounts.views (ns status-im.ui.screens.accounts.views
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.ui.screens.accounts.styles :as styles] [status-im.ui.screens.accounts.styles :as styles]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.actions :as act]
[status-im.ui.components.common.common :as common]
[status-im.ui.components.action-button.action-button :refer [action-button]]
[status-im.constants :refer [console-chat-id]]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.i18n :as i18n])) [status-im.i18n :as i18n]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn account-view [{:keys [address photo-path name public-key]}]
(defn account-badge [address photo-path name] [react/touchable-highlight {:on-press #(re-frame/dispatch [:open-login address photo-path name])}
[react/view styles/account-badge [react/view styles/account-view
[react/image {:source {:uri (if (string/blank? photo-path) :avatar photo-path)} [react/image {:source {:uri (if (string/blank? photo-path) :avatar photo-path)}
:style styles/photo-image}] :style styles/photo-image}]
[react/view styles/account-badge-text-view [react/view styles/account-badge-text-view
[react/text {:style styles/account-badge-text [react/text {:style styles/account-badge-text
:numberOfLines 1} :numberOfLines 1}
(or name address)]]]) name]
[react/text {:style styles/account-badge-pub-key-text
(defn account-view [{:keys [address photo-path name] :as account}] :ellipsize-mode :middle
[react/view :numberOfLines 1}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:open-login address photo-path name])} public-key]]
[react/view styles/account-view [react/view {:flex 1}]
[account-badge address photo-path name]]]]) [icons/icon :icons/forward {:color (colors/alpha colors/gray-icon 0.4)}]]])
(defview accounts [] (defview accounts []
[accounts [:get-accounts]] (letsubs [accounts [:get-accounts]]
[react/view styles/accounts-view
[status-bar/status-bar]
[toolbar/toolbar nil nil
[toolbar/content-title (i18n/label :t/sign-in-to-status)]]
[react/view styles/accounts-container [react/view styles/accounts-container
[status-bar/status-bar {:type :transparent}]
[react/view styles/account-title-conatiner
[react/text {:style styles/account-title-text
:font :toolbar-title}
(i18n/label :t/sign-in-to-status)]]
[react/view styles/accounts-list-container [react/view styles/accounts-list-container
[list/flat-list {:data (vals accounts) [list/flat-list {:data (vals accounts)
:render-fn (fn [account] [account-view account]) :render-fn (fn [account] [account-view account])
:separator [react/view {:height 10}]}]] :separator [react/view {:height 12}]}]]
[react/view styles/bottom-actions-container [react/view
[action-button (merge [components.common/button {:on-press #(re-frame/dispatch [:navigate-to :create-account])
{:label (i18n/label :t/create-new-account) :label (i18n/label :t/create-new-account)}]
:icon :icons/add [react/view styles/bottom-button-container
:icon-opts {:color :white} [components.common/button {:on-press #(re-frame/dispatch [:navigate-to :recover])
:on-press #(re-frame/dispatch [:create-new-account-handler])} :label (i18n/label :t/add-existing-account)
styles/accounts-action-button)] :background? false}]]]]]))
[common/separator styles/accounts-separator styles/accounts-separator-wrapper]
[action-button (merge
{:label (i18n/label :t/recover-access)
:icon :icons/dots-horizontal
:icon-opts {:color :white}
:on-press #(re-frame/dispatch [:navigate-to :recover])}
styles/accounts-action-button)]]])

View File

@ -43,10 +43,8 @@
:on-press #()}]]) :on-press #()}]])
(defview add-new [] (defview add-new []
(letsubs [contacts [:all-added-group-contacts] [react/view {:flex 1 :background-color :white}
params [:get :contacts/click-params]]
[react/view {:flex 1}
[status-bar/status-bar] [status-bar/status-bar]
[toolbar.view/simple-toolbar (i18n/label :t/new)] [toolbar.view/simple-toolbar (i18n/label :t/new)]
[components/separator] [components/separator]
[options-list]])) [options-list]])

View File

@ -15,10 +15,8 @@
:initialize-browsers :initialize-browsers
[(re-frame/inject-cofx :all-stored-browsers)] [(re-frame/inject-cofx :all-stored-browsers)]
(fn [{:keys [db all-stored-browsers]} _] (fn [{:keys [db all-stored-browsers]} _]
(let [{:accounts/keys [account-creation?]} db]
(when-not account-creation?
(let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))] (let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))]
{:db (assoc db :browser/browsers browsers)}))))) {:db (assoc db :browser/browsers browsers)})))
(re-frame/reg-fx (re-frame/reg-fx
:save-browser :save-browser

View File

@ -28,7 +28,7 @@
:group/contact-groups {} :group/contact-groups {}
:group/selected-contacts #{} :group/selected-contacts #{}
:chats {} :chats {}
:current-chat-id constants/console-chat-id :current-chat-id nil
:selected-participants #{} :selected-participants #{}
:discoveries {} :discoveries {}
:discover-search-tags #{} :discover-search-tags #{}
@ -139,8 +139,7 @@
:group/selected-contacts :group/selected-contacts
:group/groups-order :group/groups-order
:accounts/accounts :accounts/accounts
:accounts/account-creation? :accounts/create
:accounts/creating-account?
:accounts/current-account-id :accounts/current-account-id
:accounts/recover :accounts/recover
:accounts/login :accounts/login

View File

@ -57,8 +57,7 @@
(repeat (- columns extras) {:name ""}))))) (repeat (- columns extras) {:name ""})))))
(defview main [] (defview main []
(letsubs [all-dapps [:discover/all-dapps] (letsubs [all-dapps [:discover/all-dapps]]
tabs-hidden? [:tabs-hidden?]]
(let [columns 3] (let [columns 3]
(when (seq all-dapps) (when (seq all-dapps)
[react/view styles/all-dapps-container [react/view styles/all-dapps-container

View File

@ -8,7 +8,6 @@
(defview discover-all-recent [] (defview discover-all-recent []
(letsubs [discoveries [:discover/recent-discoveries] (letsubs [discoveries [:discover/recent-discoveries]
tabs-hidden? [:tabs-hidden?]
current-account [:get-current-account] current-account [:get-current-account]
contacts [:get-contacts]] contacts [:get-contacts]]
[react/view styles/all-recent-container [react/view styles/all-recent-container
@ -16,7 +15,7 @@
toolbar/default-nav-back toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/recent)]] [toolbar/content-title (i18n/label :t/recent)]]
(when (seq discoveries) (when (seq discoveries)
[react/scroll-view (styles/list-container tabs-hidden?) [react/scroll-view (styles/list-container false)
[react/view styles/status-list-outer [react/view styles/status-list-outer
[react/view styles/status-list-inner [react/view styles/status-list-inner
(let [discoveries (map-indexed vector discoveries)] (let [discoveries (map-indexed vector discoveries)]

View File

@ -24,9 +24,9 @@
status-im.ui.screens.wallet.choose-recipient.events status-im.ui.screens.wallet.choose-recipient.events
status-im.ui.screens.browser.events status-im.ui.screens.browser.events
status-im.ui.screens.offline-messaging-settings.events status-im.ui.screens.offline-messaging-settings.events
status-im.ui.screens.usage-data.events
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.ui.components.react :as react]
[status-im.ui.components.permissions :as permissions] [status-im.ui.components.permissions :as permissions]
[status-im.constants :refer [console-chat-id]] [status-im.constants :refer [console-chat-id]]
[status-im.data-store.core :as data-store] [status-im.data-store.core :as data-store]
@ -159,13 +159,14 @@
(re-frame/reg-fx (re-frame/reg-fx
:initialize-geth-fx :initialize-geth-fx
(fn [config] (fn [config]
;;TODO get rid of this, because we don't need this anymore
(status/should-move-to-internal-storage? (status/should-move-to-internal-storage?
(fn [should-move?] (fn [should-move?]
(if should-move? (if should-move?
(re-frame/dispatch [:request-permissions (re-frame/dispatch [:request-permissions
[:read-external-storage] [:read-external-storage]
#(move-to-internal-storage config) #(move-to-internal-storage config)
#(re-frame/dispatch [:move-to-internal-failure-message])]) #()])
(status/start-node config)))))) (status/start-node config))))))
(re-frame/reg-fx (re-frame/reg-fx
@ -225,7 +226,7 @@
{::testfairy-alert nil {::testfairy-alert nil
:dispatch-n [[:initialize-db] :dispatch-n [[:initialize-db]
[:load-accounts] [:load-accounts]
[:check-console-chat] [:initialize-views]
[:listen-to-network-status] [:listen-to-network-status]
[:initialize-crypt] [:initialize-crypt]
[:initialize-geth]]})) [:initialize-geth]]}))
@ -234,7 +235,6 @@
:initialize-db :initialize-db
(fn [{{:keys [status-module-initialized? status-node-started? (fn [{{:keys [status-module-initialized? status-node-started?
network-status network] network-status network]
:networks/keys [networks]
:or {network (get app-db :network)}} :db} _] :or {network (get app-db :network)}} :db} _]
{::init-store nil {::init-store nil
:db (assoc app-db :db (assoc app-db
@ -247,8 +247,8 @@
(handlers/register-handler-db (handlers/register-handler-db
:initialize-account-db :initialize-account-db
(fn [{:keys [accounts/accounts contacts/contacts networks/networks (fn [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks
network network-status view-id navigation-stack chats network network-status view-id navigation-stack
access-scope->commands-responses access-scope->commands-responses
status-module-initialized? status-node-started? status-module-initialized? status-node-started?
inbox/wnode] inbox/wnode]
@ -268,7 +268,7 @@
:status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?) :status-module-initialized? (or platform/ios? js/goog.DEBUG status-module-initialized?)
:status-node-started? status-node-started? :status-node-started? status-node-started?
:accounts/accounts accounts :accounts/accounts accounts
:accounts/creating-account? false :accounts/create create
:networks/networks networks :networks/networks networks
:network-status network-status :network-status network-status
:network network :network network
@ -291,24 +291,24 @@
[:send-account-update-if-needed] [:send-account-update-if-needed]
[:update-wallet] [:update-wallet]
[:update-transactions] [:update-transactions]
[:get-fcm-token]] [:get-fcm-token]
[:update-sign-in-time]]
(seq events-after) (seq events-after)
(into events-after))})) (into events-after))}))
(handlers/register-handler-fx (handlers/register-handler-fx
:check-console-chat :initialize-views
(fn [{{:accounts/keys [accounts] :as db} :db} [_ open-console?]] (fn [{{:accounts/keys [accounts] :as db} :db}]
(let [view (if (empty? accounts) {:db (if (empty? accounts)
:chat (assoc db :view-id :intro :navigation-stack (list :intro))
:accounts)] (let [{:keys [address photo-path name]} (first (sort-by :last-sign-in > (vals accounts)))]
(merge (-> db
{:db (assoc db (assoc :view-id :login
:view-id view :navigation-stack (list :login))
:navigation-stack (list view))} (update :accounts/login assoc
(when (or (empty? accounts) open-console?) :address address
{:dispatch-n (concat [[:init-console-chat]] :photo-path photo-path
(when open-console? :name name))))}))
[[:navigate-to-chat console-chat-id]]))})))))
(handlers/register-handler-fx (handlers/register-handler-fx
:initialize-crypt :initialize-crypt

View File

@ -155,3 +155,51 @@
:width 14 :width 14
:height 9 :height 9
:tint-color :white}) :tint-color :white})
(def no-chats
{:flex 1
:align-items :center
:justify-content :center
:margin-horizontal 34})
(def no-chats-text
{:font-size 14
:line-height 21
:letter-spacing -0.2
:text-align :center
:color colors/gray})
(def welcome-view
{:flex 1
:padding-horizontal 30})
(def welcome-image-container
{:flex 1
:align-items :center
:justify-content :center})
(def welcome-image
{:width 320
:height 278})
(def welcome-text
{:line-height 28
:font-size 22
:font-weight :bold
:letter-spacing -0.3
:text-align :center
:color colors/black})
(def welcome-text-description
{:line-height 21
:margin-top 8
:margin-bottom 32
:font-size 14
:letter-spacing -0.2
:text-align :center
:color colors/gray})
(def toolbar-logo
{:size 42
:icon-size 17
:shadow? false})

View File

@ -1,9 +1,7 @@
(ns status-im.ui.screens.home.views (ns status-im.ui.screens.home.views
(:require-macros [status-im.utils.views :as views]) (:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.native-action-button :refer [native-action-button]] [status-im.ui.components.native-action-button :refer [native-action-button]]
@ -12,12 +10,16 @@
[status-im.ui.components.sync-state.offline :refer [offline-view]] [status-im.ui.components.sync-state.offline :refer [offline-view]]
[status-im.ui.screens.home.views.inner-item :as inner-item] [status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.screens.home.styles :as styles] [status-im.ui.screens.home.styles :as styles]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]
[status-im.react-native.resources :as resources]
[status-im.ui.components.common.common :as components.common]
[status-im.i18n :as i18n]))
(defn- toolbar [] (defn- toolbar [show-welcome?]
[toolbar/toolbar {:title-centered? true} [toolbar/toolbar nil nil
nil (when-not show-welcome?
[toolbar/content-title (i18n/label :t/status)] [toolbar/content-wrapper
[components.common/logo styles/toolbar-logo]])
[toolbar/actions [toolbar/actions
(when platform/ios? (when platform/ios?
[(toolbar.actions/add #(re-frame/dispatch [:navigate-to :new]))])]]) [(toolbar.actions/add #(re-frame/dispatch [:navigate-to :new]))])]])
@ -38,13 +40,37 @@
[react/view [react/view
[inner-item/home-list-browser-item-inner-view home-item]]])) [inner-item/home-list-browser-item-inner-view home-item]]]))
;;do not remove view-id and will-update or will-unmount handlers, this is how it works
(views/defview welcome [view-id]
(views/letsubs [handler #(re-frame/dispatch [:set-in [:accounts/create :show-welcome?] false])]
{:component-will-update handler
:component-will-unmount handler}
[react/view {:style styles/welcome-view}
[react/view {:style styles/welcome-image-container}
[react/image {:source (:welcome-image resources/ui)
:style styles/welcome-image}]]
[react/text {:style styles/welcome-text}
(i18n/label :t/welcome-to-status)]
[react/view
[react/text {:style styles/welcome-text-description}
(i18n/label :t/welcome-to-status-description)]]]))
(views/defview home [] (views/defview home []
(views/letsubs [home-items [:home-items]] (views/letsubs [home-items [:home-items]
show-welcome? [:get-in [:accounts/create :show-welcome?]]
view-id [:get :view-id]]
[react/view styles/container [react/view styles/container
[toolbar] [toolbar show-welcome?]
(cond show-welcome?
[welcome view-id]
(empty? home-items)
[react/view styles/no-chats
[react/text {:style styles/no-chats-text}
(i18n/label :t/no-recent-chats)]]
:else
[list/flat-list {:data home-items [list/flat-list {:data home-items
:render-fn (fn [[home-item-id :as home-item]] :render-fn (fn [[home-item-id :as home-item]]
^{:key home-item-id} [home-list-item home-item])}] ^{:key home-item-id} [home-list-item home-item])}])
(when platform/android? (when platform/android?
[home-action-button]) [home-action-button])
[offline-view]])) [offline-view]]))

View File

@ -0,0 +1,43 @@
(ns status-im.ui.screens.intro.styles
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
(:require [status-im.ui.components.colors :as colors]))
(def intro-view
{:flex 1
:padding-horizontal 30
:background-color colors/white})
(def intro-logo-container
{:flex 1
:align-items :center
:justify-content :center})
(def intro-logo
{:size 111
:icon-size 46})
(defstyle intro-text
{:text-align :center
:color colors/black
:ios {:line-height 28
:font-size 22
:font-weight :bold
:letter-spacing -0.3}
:android {:font-size 24
:line-height 30}})
(def intro-text-description
{:line-height 21
:margin-top 8
:margin-bottom 16
:font-size 14
:letter-spacing -0.2
:text-align :center
:color colors/gray})
(def buttons-container
{:align-items :center})
(def bottom-button-container
{:margin-bottom 6
:margin-top 38})

View File

@ -0,0 +1,27 @@
(ns status-im.ui.screens.intro.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.intro.styles :as styles]
[status-im.i18n :as i18n]
[status-im.ui.components.status-bar.view :as status-bar]))
(defview intro []
[react/view {:style styles/intro-view}
[status-bar/status-bar {:flat? true}]
[react/view {:style styles/intro-logo-container}
[components.common/logo styles/intro-logo]]
[react/text {:style styles/intro-text}
(i18n/label :t/intro-text)]
[react/view
[react/text {:style styles/intro-text-description}
(i18n/label :t/intro-text-description)]]
[react/view styles/buttons-container
[components.common/button {:style {:flex-direction :row}
:on-press #(re-frame/dispatch [:navigate-to :create-account])
:label (i18n/label :t/create-account)}]
[react/view styles/bottom-button-container
[components.common/button {:on-press #(re-frame/dispatch [:navigate-to :recover])
:label (i18n/label :t/already-have-account)
:background? false}]]]])

View File

@ -21,9 +21,6 @@
(update :navigation-stack replace-top-element view-id) (update :navigation-stack replace-top-element view-id)
(assoc :view-id view-id))) (assoc :view-id view-id)))
(defn- can-navigate-back? [db]
(not (get db :accounts/creating-account?)))
;; public fns ;; public fns
(defn navigate-to-clean [db view-id] (defn navigate-to-clean [db view-id]
@ -89,15 +86,13 @@
(>= 1 (count navigation-stack)) db (>= 1 (count navigation-stack)) db
:else :else
(if (can-navigate-back? db)
(let [[previous-view-id :as navigation-stack'] (pop navigation-stack) (let [[previous-view-id :as navigation-stack'] (pop navigation-stack)
first-in-stack (first navigation-stack)] first-in-stack (first navigation-stack)]
(if (= view-id first-in-stack) (if (= view-id first-in-stack)
(-> db (-> db
(assoc :view-id previous-view-id) (assoc :view-id previous-view-id)
(assoc :navigation-stack navigation-stack')) (assoc :navigation-stack navigation-stack'))
(assoc db :view-id first-in-stack))) (assoc db :view-id first-in-stack))))))
db))))
(register-handler-db (register-handler-db
:navigate-to-clean :navigate-to-clean

View File

@ -3,7 +3,7 @@
[re-frame.core :refer [dispatch]] [re-frame.core :refer [dispatch]]
[status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.text-input-with-label.view :refer [text-input-with-label]] [status-im.ui.components.text-input.view :as text-input]
[status-im.ui.screens.network-settings.views :as network-settings] [status-im.ui.screens.network-settings.views :as network-settings]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.sticky-button :as sticky-button] [status-im.ui.components.sticky-button :as sticky-button]
@ -18,7 +18,7 @@
(i18n/label :t/add-network)] (i18n/label :t/add-network)]
[network-settings/network-badge] [network-settings/network-badge]
[react/view {:margin-top 8} [react/view {:margin-top 8}
[text-input-with-label {:label (i18n/label :t/rpc-url)}]] [text-input/text-input-with-label {:label (i18n/label :t/rpc-url)}]]
[react/view {:flex 1}] [react/view {:flex 1}]
(when (not (str/blank? rpc-url)) (when (not (str/blank? rpc-url))
[sticky-button/sticky-button (i18n/label :t/add-network) #()])])) [sticky-button/sticky-button (i18n/label :t/add-network) #()])]))

View File

@ -6,7 +6,7 @@
:padding-top 24}) :padding-top 24})
(def action (def action
{:background-color colors/blue-transparent {:background-color (colors/alpha colors/blue 0.1)
:border-radius 50}) :border-radius 50})
(def action-label (def action-label

View File

@ -11,7 +11,7 @@
:align-items :center :align-items :center
:height 42 :height 42
:border-radius components.styles/border-radius :border-radius components.styles/border-radius
:background-color colors/blue-transparent}) :background-color (colors/alpha colors/blue 0.1)})
(def share-contact-code-text-container (def share-contact-code-text-container
{:padding-left 16 {:padding-left 16

View File

@ -31,13 +31,6 @@
(fn [current-account] (fn [current-account]
(:signed-up? current-account))) (:signed-up? current-account)))
(reg-sub :tabs-hidden?
:<- [:get-in [:chat-list-ui-props :edit?]]
:<- [:get-in [:contacts/ui-props :edit?]]
:<- [:get :view-id]
(fn [[chats-edit-mode? contacts-edit-mode? view-id]]
(and (= view-id :contact-list) contacts-edit-mode?)))
(reg-sub :network (reg-sub :network
(fn [db] (fn [db]
(:network db))) (:network db)))
@ -54,3 +47,7 @@
(reg-sub :get-screen-params (reg-sub :get-screen-params
(fn [db [_ view-id]] (fn [db [_ view-id]]
(get-in db [:navigation/screen-params (or view-id (:view-id db))]))) (get-in db [:navigation/screen-params (or view-id (:view-id db))])))
(reg-sub :can-navigate-back?
(fn [db]
(> (count (:navigation-stack db)) 1)))

View File

@ -0,0 +1,10 @@
(ns status-im.ui.screens.usage-data.events
(:require [status-im.utils.handlers :as handlers]
[status-im.ui.screens.accounts.events :as accounts]))
(handlers/register-handler-fx
:help-improve-handler
(fn [{db :db} [_ yes?]]
(merge (when yes?
(accounts/account-update {:db db} {:sharing-usage-data? true}))
{:dispatch [:navigate-to-clean :home]})))

View File

@ -0,0 +1,48 @@
(ns status-im.ui.screens.usage-data.styles
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
(:require [status-im.ui.components.colors :as colors]))
(def usage-data-view
{:flex 1
:padding-horizontal 30
:background-color colors/white})
(def logo-container
{:flex 1
:align-items :center
:justify-content :center})
(def logo
{:size 82
:icon-size 34})
(def usage-data-image
{:width 138
:height 208
:margin-top 10})
(defstyle help-improve-text
{:text-align :center
:color colors/black
:ios {:line-height 28
:font-size 22
:font-weight :bold
:letter-spacing -0.3}
:android {:font-size 24
:line-height 30}})
(def help-improve-text-description
{:line-height 21
:margin-top 8
:margin-bottom 16
:font-size 14
:letter-spacing -0.2
:text-align :center
:color colors/gray})
(def buttons-container
{:align-items :center})
(def bottom-button-container
{:margin-bottom 6
:margin-top 38})

View File

@ -0,0 +1,30 @@
(ns status-im.ui.screens.usage-data.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.react :as react]
[re-frame.core :as re-frame]
[status-im.react-native.resources :as resources]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.screens.usage-data.styles :as styles]
[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}]]]])

View File

@ -7,7 +7,7 @@
[status-im.ui.screens.main-tabs.views :refer [main-tabs]] [status-im.ui.screens.main-tabs.views :refer [main-tabs]]
[status-im.ui.screens.accounts.login.views :refer [login]] [status-im.ui.screens.accounts.login.views :refer [login]]
[status-im.ui.screens.accounts.recover.views :refer [recover recover-modal]] [status-im.ui.screens.accounts.recover.views :refer [recover]]
[status-im.ui.screens.accounts.views :refer [accounts]] [status-im.ui.screens.accounts.views :refer [accounts]]
[status-im.chat.screen :refer [chat]] [status-im.chat.screen :refer [chat]]
@ -38,7 +38,6 @@
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions] [status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
[status-im.ui.screens.wallet.send.transaction-sent.views :refer [transaction-sent transaction-sent-modal]] [status-im.ui.screens.wallet.send.transaction-sent.views :refer [transaction-sent transaction-sent-modal]]
[status-im.ui.screens.wallet.components.views :refer [contact-code recent-recipients recipient-qr-code]] [status-im.ui.screens.wallet.components.views :refer [contact-code recent-recipients recipient-qr-code]]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.screens.discover.search-results.views :as discover-search] [status-im.ui.screens.discover.search-results.views :as discover-search]
[status-im.ui.screens.discover.recent-statuses.views :as discover-recent] [status-im.ui.screens.discover.recent-statuses.views :as discover-recent]
[status-im.ui.screens.discover.all-dapps.views :as discover-all-dapps] [status-im.ui.screens.discover.all-dapps.views :as discover-all-dapps]
@ -51,15 +50,11 @@
[status-im.ui.screens.network-settings.parse-json.views :refer [paste-json-text]] [status-im.ui.screens.network-settings.parse-json.views :refer [paste-json-text]]
[status-im.ui.screens.browser.views :refer [browser]] [status-im.ui.screens.browser.views :refer [browser]]
[status-im.ui.screens.add-new.open-dapp.views :refer [open-dapp dapp-description]] [status-im.ui.screens.add-new.open-dapp.views :refer [open-dapp dapp-description]]
[status-im.ui.screens.intro.views :refer [intro]]
[status-im.ui.screens.accounts.create.views :refer [create-account]]
[status-im.ui.screens.usage-data.views :refer [usage-data]]
[status-im.utils.config :as config])) [status-im.utils.config :as config]))
(defn validate-current-view
[current-view signed-up?]
(if (or (contains? #{:login :chat :recover :accounts} current-view)
signed-up?)
current-view
:chat))
;;; defines hierarchy of views, when parent screen is opened children screens ;;; defines hierarchy of views, when parent screen is opened children screens
;;; are pre-rendered, currently it is: ;;; are pre-rendered, currently it is:
;;; ;;;
@ -129,8 +124,10 @@
modal-view [:get :modal]] modal-view [:get :modal]]
{:component-will-update (fn [] (react/dismiss-keyboard!))} {:component-will-update (fn [] (react/dismiss-keyboard!))}
(when view-id (when view-id
(let [current-view (validate-current-view view-id signed-up?)] (let [component (case view-id
(let [component (case current-view :intro intro
:create-account create-account
:usage-data usage-data
(:home :wallet :my-profile) main-tabs (:home :wallet :my-profile) main-tabs
:browser browser :browser browser
:open-dapp open-dapp :open-dapp open-dapp
@ -173,8 +170,8 @@
:recipient-qr-code recipient-qr-code :recipient-qr-code recipient-qr-code
:contact-code contact-code :contact-code contact-code
:profile-qr-viewer profile.user/qr-viewer :profile-qr-viewer profile.user/qr-viewer
(throw (str "Unknown view: " current-view))) [react/view [react/text (str "Unknown view: " view-id)]])
main-screen-view (create-main-screen-view current-view)] main-screen-view (create-main-screen-view view-id)]
[main-screen-view common-styles/flex [main-screen-view common-styles/flex
(if (and config/compile-views-enabled? (if (and config/compile-views-enabled?
signed-up? signed-up?
@ -182,7 +179,7 @@
:choose-recipient :wallet-transaction-sent :transactions-history :choose-recipient :wallet-transaction-sent :transactions-history
:unsigned-transactions :wallet-request-transaction :edit-my-profile :unsigned-transactions :wallet-request-transaction :edit-my-profile
:profile-photo-capture :wallet-request-assets} :profile-photo-capture :wallet-request-assets}
current-view)) view-id))
[root-view] [root-view]
[component]) [component])
(when modal-view (when modal-view
@ -192,13 +189,12 @@
:on-request-close #(dispatch [:navigate-back])} :on-request-close #(dispatch [:navigate-back])}
(let [component (case modal-view (let [component (case modal-view
:qr-scanner qr-scanner :qr-scanner qr-scanner
:recover-modal recover-modal
:contact-list-modal contact-list-modal :contact-list-modal contact-list-modal
:wallet-transactions-filter wallet-transactions/filter-history :wallet-transactions-filter wallet-transactions/filter-history
:wallet-settings-assets wallet-settings/manage-assets :wallet-settings-assets wallet-settings/manage-assets
:wallet-send-transaction-modal send-transaction-modal :wallet-send-transaction-modal send-transaction-modal
:wallet-transaction-sent-modal transaction-sent-modal :wallet-transaction-sent-modal transaction-sent-modal
:wallet-transaction-fee wallet.send/transaction-fee :wallet-transaction-fee wallet.send/transaction-fee
(throw (str "Unknown modal view: " modal-view)))] [react/view [react/text (str "Unknown modal view: " modal-view)]])]
[react/main-screen-modal-view modal-view [react/main-screen-modal-view modal-view
[component]])]])]))))) [component]])]])]))))

View File

@ -1,12 +0,0 @@
(ns status-im.ui.screens.wallet.components.animations
(:require [status-im.ui.components.animation :as animation]))
(defn animate-tooltip [bottom-value opacity-value]
(fn []
(animation/start
(animation/parallel
[(animation/timing opacity-value {:toValue 1
:duration 500})
(animation/timing bottom-value {:toValue -40
:easing (.bezier (animation/easing) 0.685, 0.000, 0.025, 1.185)
:duration 500})]))))

View File

@ -184,31 +184,4 @@
:font-size 15 :font-size 15
:letter-spacing -0.2}) :letter-spacing -0.2})
(def tooltip-container
{:position :absolute
:align-items :center
:left 0
:right 0
:top 0})
(defn tooltip-animated [bottom-value opacity-value]
{:position :absolute
:align-items :center
:left 0
:right 0
:bottom bottom-value
:opacity opacity-value})
(def tooltip-text-container
{:padding-horizontal 16
:padding-vertical 9
:background-color :white
:border-radius 8})
(def tooltip-text
{:color styles/color-red-2
:font-size 15})
(def tooltip-triangle
{:width 16
:height 8})

View File

@ -4,18 +4,15 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.bottom-buttons.view :as bottom-buttons] [status-im.ui.components.bottom-buttons.view :as bottom-buttons]
[status-im.ui.components.button.view :as button] [status-im.ui.components.button.view :as button]
[status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.components.list.styles :as list.styles] [status-im.ui.components.list.styles :as list.styles]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.styles :as components.styles] [status-im.ui.components.styles :as components.styles]
[status-im.ui.screens.wallet.components :as components] [status-im.ui.screens.wallet.components :as components]
[status-im.ui.screens.wallet.components.animations :as animations]
[status-im.ui.screens.wallet.components.styles :as styles] [status-im.ui.screens.wallet.components.styles :as styles]
[status-im.ui.screens.wallet.choose-recipient.views :as choose-recipient] [status-im.ui.screens.wallet.choose-recipient.views :as choose-recipient]
[status-im.ui.screens.wallet.views :as wallet] [status-im.ui.screens.wallet.views :as wallet]
@ -23,17 +20,8 @@
[status-im.ui.screens.wallet.utils :as wallet.utils] [status-im.ui.screens.wallet.utils :as wallet.utils]
[status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.ethereum.tokens :as tokens] [status-im.utils.ethereum.tokens :as tokens]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]
[status-im.ui.components.tooltip.views :as tooltip]))
(views/defview tooltip [label]
(views/letsubs [bottom-value (animation/create-value -30)
opacity-value (animation/create-value 0)]
{:component-did-mount (animations/animate-tooltip bottom-value opacity-value)}
[react/view styles/tooltip-container
[react/animated-view {:style (styles/tooltip-animated bottom-value opacity-value)}
[react/view styles/tooltip-text-container
[react/text {:style styles/tooltip-text} label]]
[vector-icons/icon :icons/tooltip-triangle {:color :white :style styles/tooltip-triangle}]]]))
(defn view-asset [symbol] (defn view-asset [symbol]
[react/view [react/view
@ -198,7 +186,7 @@
(i18n/label :t/amount) (i18n/label :t/amount)
[amount-input m]] [amount-input m]]
(when error (when error
[tooltip error])]) [tooltip/tooltip error])])
(defn separator [] (defn separator []
[react/view styles/separator]) [react/view styles/separator])

View File

@ -12,6 +12,7 @@
[status-im.ui.components.styles :as components.styles] [status-im.ui.components.styles :as components.styles]
[status-im.ui.components.toolbar.actions :as act] [status-im.ui.components.toolbar.actions :as act]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.tooltip.views :as tooltip]
[status-im.ui.screens.wallet.components.styles :as wallet.components.styles] [status-im.ui.screens.wallet.components.styles :as wallet.components.styles]
[status-im.ui.screens.wallet.components.views :as components] [status-im.ui.screens.wallet.components.views :as components]
[status-im.ui.screens.wallet.components :as wallet.components] [status-im.ui.screens.wallet.components :as wallet.components]
@ -51,7 +52,7 @@
:on-change-text #(re-frame/dispatch [:wallet.send/set-password %]) :on-change-text #(re-frame/dispatch [:wallet.send/set-password %])
:style styles/password}]]] :style styles/password}]]]
(when wrong-password? (when wrong-password?
[components/tooltip (i18n/label :t/wrong-password)])])) [tooltip/tooltip (i18n/label :t/wrong-password)])]))
;; "Cancel" and "Sign Transaction >" buttons, signing with password ;; "Cancel" and "Sign Transaction >" buttons, signing with password
(defview signing-buttons [cancel-handler sign-handler in-progress?] (defview signing-buttons [cancel-handler sign-handler in-progress?]

View File

@ -216,4 +216,7 @@
(def filter-container (def filter-container
{:flex 1}) {:flex 1})
;:background-color colors/white})
(def transacions-view
{:flex 1
:background-color :white})

View File

@ -28,7 +28,7 @@
(every? :checked? (:tokens filter-data)))) (every? :checked? (:tokens filter-data))))
(defn- toolbar-view [current-tab filter-data] (defn- toolbar-view [current-tab filter-data]
[toolbar/toolbar {:flat? true} [toolbar/toolbar nil
toolbar/default-nav-back toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/transactions)] [toolbar/content-title (i18n/label :t/transactions)]
(case current-tab (case current-tab
@ -187,7 +187,7 @@
(defview transactions [] (defview transactions []
(letsubs [current-tab [:get :view-id] (letsubs [current-tab [:get :view-id]
filter-data [:wallet.transactions/filters]] filter-data [:wallet.transactions/filters]]
[react/view {:style components.styles/flex} [react/view styles/transacions-view
[status-bar/status-bar] [status-bar/status-bar]
[toolbar-view current-tab filter-data] [toolbar-view current-tab filter-data]
[tabs current-tab] [tabs current-tab]