diff --git a/resources/icons/down.svg b/resources/icons/down.svg
index fb0ed31ea1..9ad7430a6d 100644
--- a/resources/icons/down.svg
+++ b/resources/icons/down.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/resources/icons/up.svg b/resources/icons/up.svg
index bc16ee31da..90b2386d7c 100644
--- a/resources/icons/up.svg
+++ b/resources/icons/up.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/resources/images/ui/lock.png b/resources/images/ui/lock.png
new file mode 100644
index 0000000000..5972b6f359
Binary files /dev/null and b/resources/images/ui/lock.png differ
diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs
index 38ccc93961..4fdab9cb4d 100644
--- a/src/status_im/chat/screen.cljs
+++ b/src/status_im/chat/screen.cljs
@@ -50,12 +50,11 @@
:options (actions/actions group-chat? chat-id public?)}))
(defview chat-toolbar [public?]
- (letsubs [accounts [:get-accounts]
- {:keys [group-chat name chat-id]} [:get-current-chat]]
+ (letsubs [{:keys [group-chat name chat-id]} [:get-current-chat]]
[react/view
[status-bar/status-bar]
[toolbar/platform-agnostic-toolbar {}
- toolbar/default-nav-back
+ toolbar/nav-back-count
[toolbar-content/toolbar-content-view]
[toolbar/actions [{:icon :icons/options
:icon-opts {:color :black}
diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs
index 7a8c6e1825..b68d8e38c8 100644
--- a/src/status_im/chat/subs.cljs
+++ b/src/status_im/chat/subs.cljs
@@ -52,15 +52,18 @@
platform/ios? kb-height
: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))))
+(defn active-chats [dev-mode?]
+ (fn [[_ chat]]
+ (and (:is-active chat)
+ (or dev-mode?
+ (not= const/console-chat-id (:chat-id chat))))))
(reg-sub
:get-active-chats
:<- [:get-chats]
- (fn [chats]
- (into {} (filter active-chats chats))))
+ :<- [:get-current-account]
+ (fn [[chats {:keys [dev-mode?]}]]
+ (into {} (filter (active-chats dev-mode?) chats))))
(reg-sub
:get-chat
@@ -324,3 +327,9 @@
(fn [db [_ key type]]
(let [chat-id (subscribe [:get-current-chat-id])]
(get-in db [:chat-animations @chat-id key type]))))
+
+(reg-sub
+ :get-chats-unread-messages-number
+ :<- [:get-active-chats]
+ (fn [chats _]
+ (apply + (map #(count (:unviewed-messages %)) (vals chats)))))
\ No newline at end of file
diff --git a/src/status_im/chat/views/toolbar_content.cljs b/src/status_im/chat/views/toolbar_content.cljs
index a501becaf8..2bdc468153 100644
--- a/src/status_im/chat/views/toolbar_content.cljs
+++ b/src/status_im/chat/views/toolbar_content.cljs
@@ -9,7 +9,9 @@
[status-im.utils.datetime :as time]
[status-im.utils.platform :refer [platform-specific]]
[status-im.utils.gfycat.core :refer [generate-gfy]]
- [status-im.constants :refer [console-chat-id]]))
+ [status-im.constants :refer [console-chat-id]]
+ [status-im.ui.components.common.common :as components.common]
+ [status-im.ui.components.styles :as common.styles]))
(defn- online-text [contact chat-id]
(cond
@@ -67,21 +69,22 @@
accounts [:get-accounts]
contact [:get-in [:contacts/contacts @chat-id]]
sync-state [:sync-state]]
- [react/view (st/chat-name-view (or (empty? accounts)
- show-actions?))
- (let [chat-name (if (string/blank? name)
- (generate-gfy public-key)
- (or (i18n/get-contact-translated chat-id :name name)
- (i18n/label :t/chat-name)))]
- [react/text {:style st/chat-name-text
- :number-of-lines 1
- :font :toolbar-title}
- (if public?
- (str "#" chat-name)
- chat-name)])
- (if group-chat
- [group-last-activity {:contacts contacts
- :public? public?
- :sync-state sync-state}]
- [last-activity {:online-text (online-text contact chat-id)
- :sync-state sync-state}])]))
+ [react/view common.styles/flex
+ [react/view (st/chat-name-view (or (empty? accounts)
+ show-actions?))
+ (let [chat-name (if (string/blank? name)
+ (generate-gfy public-key)
+ (or (i18n/get-contact-translated chat-id :name name)
+ (i18n/label :t/chat-name)))]
+ [react/text {:style st/chat-name-text
+ :number-of-lines 1
+ :font :toolbar-title}
+ (if public?
+ (str "#" chat-name)
+ chat-name)])
+ (if group-chat
+ [group-last-activity {:contacts contacts
+ :public? public?
+ :sync-state sync-state}]
+ [last-activity {:online-text (online-text contact chat-id)
+ :sync-state sync-state}])]]))
diff --git a/src/status_im/data_store/realm/schemas/base/core.cljs b/src/status_im/data_store/realm/schemas/base/core.cljs
index f140d9021a..6ba8ede945 100644
--- a/src/status_im/data_store/realm/schemas/base/core.cljs
+++ b/src/status_im/data_store/realm/schemas/base/core.cljs
@@ -5,7 +5,8 @@
[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.v6.core :as v6]
- [status-im.data-store.realm.schemas.base.v7.core :as v7]))
+ [status-im.data-store.realm.schemas.base.v7.core :as v7]
+ [status-im.data-store.realm.schemas.base.v8.core :as v8]))
;; put schemas ordered by version
(def schemas [{:schema v1/schema
@@ -28,4 +29,7 @@
:migration v6/migration}
{:schema v7/schema
:schemaVersion 7
- :migration v7/migration}])
+ :migration v7/migration}
+ {:schema v8/schema
+ :schemaVersion 8
+ :migration v8/migration}])
diff --git a/src/status_im/data_store/realm/schemas/base/v8/account.cljs b/src/status_im/data_store/realm/schemas/base/v8/account.cljs
new file mode 100644
index 0000000000..07ca6bfa5f
--- /dev/null
+++ b/src/status_im/data_store/realm/schemas/base/v8/account.cljs
@@ -0,0 +1,29 @@
+(ns status-im.data-store.realm.schemas.base.v8.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}
+ :mnemonic {: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}
+ :dev-mode? {:type :bool :default false}
+ :seed-backed-up? {:type :bool :default false}}})
\ No newline at end of file
diff --git a/src/status_im/data_store/realm/schemas/base/v8/core.cljs b/src/status_im/data_store/realm/schemas/base/v8/core.cljs
new file mode 100644
index 0000000000..63e2ba42b1
--- /dev/null
+++ b/src/status_im/data_store/realm/schemas/base/v8/core.cljs
@@ -0,0 +1,10 @@
+(ns status-im.data-store.realm.schemas.base.v8.core
+ (:require [status-im.data-store.realm.schemas.base.v4.network :as network]
+ [status-im.data-store.realm.schemas.base.v8.account :as account]
+ [taoensso.timbre :as log]))
+
+(def schema [network/schema
+ account/schema])
+
+(defn migration [old-realm new-realm]
+ (log/debug "migrating v8 base database: " old-realm new-realm))
diff --git a/src/status_im/react_native/resources.cljs b/src/status_im/react_native/resources.cljs
index 99c146ef20..5d5fbdde0e 100644
--- a/src/status_im/react_native/resources.cljs
+++ b/src/status_im/react_native/resources.cljs
@@ -24,4 +24,5 @@
{:empty-hashtags (js/require "./resources/images/ui/empty-hashtags.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")})
\ No newline at end of file
+ :welcome-image (js/require "./resources/images/ui/welcome-image.png")
+ :lock (js/require "./resources/images/ui/lock.png")})
\ No newline at end of file
diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs
index fb9695753c..13d3f70742 100644
--- a/src/status_im/translations/en.cljs
+++ b/src/status_im/translations/en.cljs
@@ -3,470 +3,488 @@
(def translations
{
;;common
- :members-title "Members"
- :not-implemented "!not implemented"
- :chat-name "Chat name"
- :notifications-title "Notifications and sounds"
- :offline "Offline"
- :connection-problem "Messages connection problem"
- :search-for "Search for..."
- :cancel "Cancel"
- :next "Next"
- :open "Open"
- :description "Description"
- :enter-url "Enter URL"
- :open-dapp "Open ÐApp"
- :url "URL"
- :type-a-message "Type a message..."
- :type-a-command "Start typing a command..."
- :error "Error"
- :unknown-status-go-error "Unknown status-go error"
- :node-unavailable "No ethereum node running"
- :add "Add"
- :yes "Yes"
- :no "No"
+ :members-title "Members"
+ :not-implemented "!not implemented"
+ :chat-name "Chat name"
+ :notifications-title "Notifications and sounds"
+ :offline "Offline"
+ :connection-problem "Messages connection problem"
+ :search-for "Search for..."
+ :cancel "Cancel"
+ :next "Next"
+ :open "Open"
+ :description "Description"
+ :enter-url "Enter URL"
+ :open-dapp "Open ÐApp"
+ :url "URL"
+ :type-a-message "Type a message..."
+ :type-a-command "Start typing a command..."
+ :error "Error"
+ :unknown-status-go-error "Unknown status-go error"
+ :node-unavailable "No ethereum node running"
+ :add "Add"
+ :yes "Yes"
+ :no "No"
- :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."
+ :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."
;;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…"
+ :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"
+ :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
- :switch-users "Switch users"
- :logout-title "Log out?"
- :logout-are-you-sure "Are you sure you want\nto log out?"
- :logout "Log out"
- :current-network "Current network"
+ :switch-users "Switch users"
+ :logout-title "Log out?"
+ :logout-are-you-sure "Are you sure you want\nto log out?"
+ :logout "Log out"
+ :current-network "Current network"
;;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"
+ :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
- :is-typing "is typing"
- :and-you "and you"
- :search-chat "Search chat"
- :members {:one "1 member"
- :other "{{count}} members"
- :zero "no members"}
- :members-active {:one "1 member"
- :other "{{count}} members"
- :zero "no members"}
- :public-group-status "Public"
- :active-online "Online"
- :active-unknown "Unknown"
- :available "Available"
- :no-messages "No messages"
- :suggestions-requests "Requests"
- :suggestions-commands "Commands"
- :faucet-success "Faucet request has been received"
- :faucet-error "Faucet request error"
+ :is-typing "is typing"
+ :and-you "and you"
+ :search-chat "Search chat"
+ :members {:one "1 member"
+ :other "{{count}} members"
+ :zero "no members"}
+ :members-active {:one "1 member"
+ :other "{{count}} members"
+ :zero "no members"}
+ :public-group-status "Public"
+ :active-online "Online"
+ :active-unknown "Unknown"
+ :available "Available"
+ :no-messages "No messages"
+ :suggestions-requests "Requests"
+ :suggestions-commands "Commands"
+ :faucet-success "Faucet request has been received"
+ :faucet-error "Faucet request error"
;;sync
- :sync-in-progress "Syncing..."
- :sync-synced "In sync"
+ :sync-in-progress "Syncing..."
+ :sync-synced "In sync"
;;messages
- :status-sending "Sending..."
- :status-pending "Pending"
- :status-sent "Sent"
- :status-seen-by-everyone "Seen by everyone"
- :status-seen "Seen"
- :status-delivered "Delivered"
- :status-failed "Failed"
+ :status-sending "Sending..."
+ :status-pending "Pending"
+ :status-sent "Sent"
+ :status-seen-by-everyone "Seen by everyone"
+ :status-seen "Seen"
+ :status-delivered "Delivered"
+ :status-failed "Failed"
;;datetime
- :datetime-ago-format "{{number}} {{time-intervals}} {{ago}}"
- :datetime-second {:one "second"
- :other "seconds"}
- :datetime-minute {:one "minute"
- :other "minutes"}
- :datetime-hour {:one "hour"
- :other "hours"}
- :datetime-day {:one "day"
- :other "days"}
- :datetime-ago "ago"
- :datetime-yesterday "yesterday"
- :datetime-today "today"
+ :datetime-ago-format "{{number}} {{time-intervals}} {{ago}}"
+ :datetime-second {:one "second"
+ :other "seconds"}
+ :datetime-minute {:one "minute"
+ :other "minutes"}
+ :datetime-hour {:one "hour"
+ :other "hours"}
+ :datetime-day {:one "day"
+ :other "days"}
+ :datetime-ago "ago"
+ :datetime-yesterday "yesterday"
+ :datetime-today "today"
;;profile
- :profile "Profile"
- :view-profile "View profile"
- :edit-profile "Edit profile"
- :main-currency "Main currency"
- :message "Message"
- :notifications "Notifications"
- :not-specified "Not specified"
- :public-key "Public key"
- :phone-number "Phone number"
- :share-contact-code "Share my contact code"
- :update-status "Update your status..."
- :add-a-status "Add a status..."
- :status-prompt "Set your status. Using #hastags will help others discover you and talk about what's on your mind"
- :contact-code "Contact code"
- :add-to-contacts "Add to contacts"
- :in-contacts "In contacts"
- :remove-from-contacts "Remove from contacts"
- :start-conversation "Start conversation"
- :send-message "Send message"
- :testnet-text "You’re on the {{testnet}} Testnet. Do not send real ETH or SNT to your address"
- :mainnet-text "You’re on the Mainnet. Real ETH will be sent"
+ :profile "Profile"
+ :view-profile "View profile"
+ :edit-profile "Edit profile"
+ :main-currency "Main currency"
+ :message "Message"
+ :notifications "Notifications"
+ :not-specified "Not specified"
+ :public-key "Public key"
+ :phone-number "Phone number"
+ :share-contact-code "Share my contact code"
+ :update-status "Update your status..."
+ :add-a-status "Add a status..."
+ :status-prompt "Set your status. Using #hastags will help others discover you and talk about what's on your mind"
+ :contact-code "Contact code"
+ :add-to-contacts "Add to contacts"
+ :in-contacts "In contacts"
+ :remove-from-contacts "Remove from contacts"
+ :start-conversation "Start conversation"
+ :send-message "Send message"
+ :testnet-text "You’re on the {{testnet}} Testnet. Do not send real ETH or SNT to your address"
+ :mainnet-text "You’re on the Mainnet. Real ETH will be sent"
+ :dev-mode "Development mode"
+ :backup-your-seed "Backup your Seed Phrase"
+
+ ;;seed
+ :your-data-belongs-to-you "Your Data and Funds belong to you. We can’t help get it back if you loose it"
+ :your-data-belongs-to-you-description "This means Status can’t help you get it back if you lose it. You are in charge of the secuty of all your data"
+ :ok-continue "Ok, continue"
+ :your-seed-phrase "Your Seed Phrase"
+ :your-seed-phrase-description "This is your seed phrase. You use it to prove that this is your wallet. You only get to see it once! Copy it on paper and keep it in a secure place. You need it when you loose or reinstall your wallet."
+ :enter-word "Enter word"
+ :check-your-seed "Check your Seed Phrase"
+ :wrong-word "Wrong word"
+ :are-you-sure? "Are you sure?"
+ :are-you-sure-description "You will not be able to see the whole seed phrase again"
+ :you-are-all-set "You’re all set!"
+ :you-are-all-set-description "Now if you loose your phone you can restore your account and wallet using the Seed Phrase and password"
+ :ok-got-it "Ok, got it"
+ :backup-seed-phrase "Backup Seed Phrase"
+ :step-i-of-n "Step {{step}} of {{number}}"
+ :word-n-description "In order to check if have backed up your seed phrase correctly, enter the word #{{number}} above"
+ :word-n "Word #{{number}}"
;;make_photo
- :image-source-title "Edit picture"
- :image-source-make-photo "Capture"
- :image-source-gallery "Select from gallery"
+ :image-source-title "Edit picture"
+ :image-source-make-photo "Capture"
+ :image-source-gallery "Select from gallery"
;;sharing
- :sharing-copy-to-clipboard "Copy to clipboard"
- :sharing-share "Share..."
- :sharing-cancel "Cancel"
+ :sharing-copy-to-clipboard "Copy to clipboard"
+ :sharing-share "Share..."
+ :sharing-cancel "Cancel"
- :browsing-title "Browse"
- :browsing-open-in-web-browser "Open in web browser"
- :browsing-open-in-browser "Open in browser"
- :browsing-cancel "Cancel"
+ :browsing-title "Browse"
+ :browsing-open-in-web-browser "Open in web browser"
+ :browsing-open-in-browser "Open in browser"
+ :browsing-cancel "Cancel"
;;sign-up
- :contacts-syncronized "Your contacts have been synchronized"
- :confirmation-code (str "Thanks! We've sent you a text message with a confirmation "
- "code. Please provide that code to confirm your phone number")
- :incorrect-code (str "Sorry the code was incorrect, please enter it again")
- :phew-here-is-your-passphrase "Phew, that was hard. Here is your passphrase, *write this down and keep it safe!* You will need it to recover your account."
- :here-is-your-passphrase "Here is your passphrase, *write this down and keep this safe!* You will need it to recover your account."
- :here-is-your-signing-phrase "Here is your signing phrase. You will use it to verify your transactions. *Write it down and keep it safe!*"
- :phone-number-required "Tap here to validate your phone number & I'll find your friends."
- :shake-your-phone "Found a bug or have a suggestion? Just ~shake~ your phone!"
- :intro-status "Chat with me to setup your account and change your settings."
- :intro-message1 "Welcome to Status!\nTap this message to set your password and get started."
- :account-generation-message "Gimmie a sec, I gotta do some crazy math to generate your account!"
- :move-to-internal-failure-message "We need to move some important files from external to internal storage. To do this, we need your permission. We won't be using external storage in future versions."
- :debug-enabled "Debug server has been launched! You can now execute *status-dev-cli scan* to find the server from your computer on the same network."
+ :contacts-syncronized "Your contacts have been synchronized"
+ :confirmation-code (str "Thanks! We've sent you a text message with a confirmation "
+ "code. Please provide that code to confirm your phone number")
+ :incorrect-code (str "Sorry the code was incorrect, please enter it again")
+ :phew-here-is-your-passphrase "Phew, that was hard. Here is your passphrase, *write this down and keep it safe!* You will need it to recover your account."
+ :here-is-your-passphrase "Here is your passphrase, *write this down and keep this safe!* You will need it to recover your account."
+ :here-is-your-signing-phrase "Here is your signing phrase. You will use it to verify your transactions. *Write it down and keep it safe!*"
+ :phone-number-required "Tap here to validate your phone number & I'll find your friends."
+ :shake-your-phone "Found a bug or have a suggestion? Just ~shake~ your phone!"
+ :intro-status "Chat with me to setup your account and change your settings."
+ :intro-message1 "Welcome to Status!\nTap this message to set your password and get started."
+ :account-generation-message "Gimmie a sec, I gotta do some crazy math to generate your account!"
+ :move-to-internal-failure-message "We need to move some important files from external to internal storage. To do this, we need your permission. We won't be using external storage in future versions."
+ :debug-enabled "Debug server has been launched! You can now execute *status-dev-cli scan* to find the server from your computer on the same network."
;;phone types
- :phone-e164 "International 1"
- :phone-international "International 2"
- :phone-national "National"
- :phone-significant "Significant"
+ :phone-e164 "International 1"
+ :phone-international "International 2"
+ :phone-national "National"
+ :phone-significant "Significant"
;;chats
- :new "New"
- :new-chat "New chat"
- :start-new-chat "Start new chat"
- :start-group-chat "Start group chat"
- :invite-friends "Invite friends"
- :get-status-at "Get Status at http://status.im?refCode={{address}}"
- :chats "Chats"
- :delete-chat "Delete chat"
- :group-chat "Group chat"
- :group-info "Group info"
- :delete-chat-confirmation "Are you sure you want to delete this chat?"
- :delete-group-chat-confirmation "Are you sure you want to delete this group chat?"
- :new-group-chat "New group chat"
- :new-public-group-chat "Join public chat"
- :public-chat "Public chat"
- :edit-chats "Edit chats"
- :search-chats "Search chats"
- :empty-topic "Empty topic"
- :topic-format "Wrong format [a-z0-9\\-]+"
- :public-group-topic "Topic"
- :set-a-topic "Set a topic"
- :empty-chat-description "There are no messages \nin this chat yet"
+ :new "New"
+ :new-chat "New chat"
+ :start-new-chat "Start new chat"
+ :start-group-chat "Start group chat"
+ :invite-friends "Invite friends"
+ :get-status-at "Get Status at http://status.im?refCode={{address}}"
+ :chats "Chats"
+ :delete-chat "Delete chat"
+ :group-chat "Group chat"
+ :group-info "Group info"
+ :delete-chat-confirmation "Are you sure you want to delete this chat?"
+ :delete-group-chat-confirmation "Are you sure you want to delete this group chat?"
+ :new-group-chat "New group chat"
+ :new-public-group-chat "Join public chat"
+ :public-chat "Public chat"
+ :edit-chats "Edit chats"
+ :search-chats "Search chats"
+ :empty-topic "Empty topic"
+ :topic-format "Wrong format [a-z0-9\\-]+"
+ :public-group-topic "Topic"
+ :set-a-topic "Set a topic"
+ :empty-chat-description "There are no messages \nin this chat yet"
;;discover
- :discover "Discover"
- :none "None"
- :search-tags "Type your search tags here"
- :popular-tags "Popular #hashtags"
- :recent "Recent statuses"
- :no-statuses-found "No statuses found"
- :chat "Chat"
- :all "All"
- :public-chats "Public chats"
- :soon "Soon"
- :public-chat-user-count "{{count}} people"
- :dapps "ÐApps"
- :dapp-profile "ÐApp profile"
- :no-statuses-discovered "No statuses discovered"
- :no-statuses-discovered-body "When somebody posts\na status you will see it here."
- :no-hashtags-discovered-title "No #hashtags discovered"
- :no-hashtags-discovered-body "When a #hashtag becomes\npopular you will see it here."
+ :discover "Discover"
+ :none "None"
+ :search-tags "Type your search tags here"
+ :popular-tags "Popular #hashtags"
+ :recent "Recent statuses"
+ :no-statuses-found "No statuses found"
+ :chat "Chat"
+ :all "All"
+ :public-chats "Public chats"
+ :soon "Soon"
+ :public-chat-user-count "{{count}} people"
+ :dapps "ÐApps"
+ :dapp-profile "ÐApp profile"
+ :no-statuses-discovered "No statuses discovered"
+ :no-statuses-discovered-body "When somebody posts\na status you will see it here."
+ :no-hashtags-discovered-title "No #hashtags discovered"
+ :no-hashtags-discovered-body "When a #hashtag becomes\npopular you will see it here."
;;settings
- :settings "Settings"
+ :settings "Settings"
;;contacts
- :contacts "Contacts"
- :new-contact "New contact"
- :delete-contact "Delete contact"
- :delete-contact-confirmation "This contact will be removed from your contacts"
- :remove-from-group "Remove from group"
- :edit-contacts "Edit contacts"
- :search-contacts "Search contacts"
- :contacts-group-new-chat "Start new chat"
- :choose-from-contacts "Choose from contacts"
- :no-contacts "No contacts yet"
- :show-qr "Show QR code"
- :qr-code-public-key-hint "Share this code to \nstart chatting"
- :enter-address "Enter address"
- :enter-contact-code "Enter contact code"
- :more "more"
+ :contacts "Contacts"
+ :new-contact "New contact"
+ :delete-contact "Delete contact"
+ :delete-contact-confirmation "This contact will be removed from your contacts"
+ :remove-from-group "Remove from group"
+ :edit-contacts "Edit contacts"
+ :search-contacts "Search contacts"
+ :contacts-group-new-chat "Start new chat"
+ :choose-from-contacts "Choose from contacts"
+ :no-contacts "No contacts yet"
+ :show-qr "Show QR code"
+ :qr-code-public-key-hint "Share this code to \nstart chatting"
+ :enter-address "Enter address"
+ :enter-contact-code "Enter contact code"
+ :more "more"
;;group-settings
- :remove "Remove"
- :save "Save"
- :create "Create"
- :delete "Delete"
- :delete-confirmation "Delete?"
- :leave "Leave"
- :leave-confirmation "Leave?"
- :clear "Clear"
- :clear-history "Clear history"
- :clear-history-title "Clear history?"
- :clear-group-history-confirmation "Are you sure you want to clear this group's chat history?"
- :clear-history-confirmation "Clear history?"
- :clear-history-action "Clear"
- :mute-notifications "Mute notifications"
- :leave-group-action "Leave"
- :leave-group-title "Leave?"
- :leave-group-confirmation "Are you sure you want to leave this group?"
- :leave-chat "Leave chat"
- :leave-group-chat-confirmation "Are you sure you want to leave this group?"
- :leave-group-chat "Leave group chat"
- :leave-group "Leave group"
- :remove-from-chat "Remove from chat"
- :delete-chat-title "Delete chat?"
- :leave-public-chat "Leave public chat"
- :chat-settings "Chat settings"
- :edit "Edit"
- :add-members "Add members"
+ :remove "Remove"
+ :save "Save"
+ :create "Create"
+ :delete "Delete"
+ :delete-confirmation "Delete?"
+ :leave "Leave"
+ :leave-confirmation "Leave?"
+ :clear "Clear"
+ :clear-history "Clear history"
+ :clear-history-title "Clear history?"
+ :clear-group-history-confirmation "Are you sure you want to clear this group's chat history?"
+ :clear-history-confirmation "Clear history?"
+ :clear-history-action "Clear"
+ :mute-notifications "Mute notifications"
+ :leave-group-action "Leave"
+ :leave-group-title "Leave?"
+ :leave-group-confirmation "Are you sure you want to leave this group?"
+ :leave-chat "Leave chat"
+ :leave-group-chat-confirmation "Are you sure you want to leave this group?"
+ :leave-group-chat "Leave group chat"
+ :leave-group "Leave group"
+ :remove-from-chat "Remove from chat"
+ :delete-chat-title "Delete chat?"
+ :leave-public-chat "Leave public chat"
+ :chat-settings "Chat settings"
+ :edit "Edit"
+ :add-members "Add members"
;;commands
- :chat-send-eth "{{amount}} ETH"
+ :chat-send-eth "{{amount}} ETH"
;;new-group
- :new-group "New group"
- :reorder-groups "Reorder groups"
- :edit-group "Edit group"
- :delete-group "Delete group"
- :delete-group-confirmation "This group will be removed from your groups. This will not affect your contacts"
- :delete-group-prompt "This will not affect your contacts"
- :contact-s {:one "contact"
- :other "contacts"}
+ :new-group "New group"
+ :reorder-groups "Reorder groups"
+ :edit-group "Edit group"
+ :delete-group "Delete group"
+ :delete-group-confirmation "This group will be removed from your groups. This will not affect your contacts"
+ :delete-group-prompt "This will not affect your contacts"
+ :contact-s {:one "contact"
+ :other "contacts"}
;;protocol
- :received-invitation "received chat invitation"
- :removed-from-chat "removed you from group chat"
- :left "left"
- :invited "invited"
- :removed "removed"
- :You "You"
+ :received-invitation "received chat invitation"
+ :removed-from-chat "removed you from group chat"
+ :left "left"
+ :invited "invited"
+ :removed "removed"
+ :You "You"
;;new-contact
- :add-new-contact "Add new contact"
- :scan-qr "Scan QR code"
- :name "Name"
- :address-explication "Your public key is used to generate your address on Ethereum and is a series of numbers and letters. You can find it easily in your profile"
- :use-valid-contact-code "Please enter a valid contact code"
- :enter-valid-public-key "Please enter a valid public key or scan a QR code"
- :contact-already-added "The contact has already been added"
- :can-not-add-yourself "You can't add yourself"
- :unknown-address "Unknown address"
+ :add-new-contact "Add new contact"
+ :scan-qr "Scan QR code"
+ :name "Name"
+ :address-explication "Your public key is used to generate your address on Ethereum and is a series of numbers and letters. You can find it easily in your profile"
+ :use-valid-contact-code "Please enter a valid contact code"
+ :enter-valid-public-key "Please enter a valid public key or scan a QR code"
+ :contact-already-added "The contact has already been added"
+ :can-not-add-yourself "You can't add yourself"
+ :unknown-address "Unknown address"
;;login
- :connect "Connect"
- :address "Address"
- :password "Password"
- :sign-in-to-status "Sign in to Status"
- :sign-in "Sign in"
- :sign-in-to-another "Sign in to another account"
- :wrong-password "Wrong password"
- :enter-password "Enter password"
+ :connect "Connect"
+ :address "Address"
+ :password "Password"
+ :sign-in-to-status "Sign in to Status"
+ :sign-in "Sign in"
+ :sign-in-to-another "Sign in to another account"
+ :wrong-password "Wrong password"
+ :enter-password "Enter password"
;;recover
- :passphrase "Passphrase"
- :recover "Recover"
- :twelve-words-in-correct-order "12 words in correct order"
- :enter-12-words "Enter the 12 words of your seed phrase"
-
+ :passphrase "Passphrase"
+ :recover "Recover"
+ :twelve-words-in-correct-order "12 words in correct order"
+ :enter-12-words "Enter the 12 words of your seed phrase"
;;accounts
- :recover-access "Recover access"
- :create-new-account "Create new account"
- :add-existing-account "Add existing account"
+ :recover-access "Recover access"
+ :create-new-account "Create new account"
+ :add-existing-account "Add existing account"
;;wallet-qr-code
- :done "Done"
+ :done "Done"
;;validation
- :invalid-phone "Invalid phone number"
- :amount "Amount"
+ :invalid-phone "Invalid phone number"
+ :amount "Amount"
;;transactions
- :confirm "Confirm"
- :transaction "Transaction"
- :unsigned-transaction-expired "Unsigned transaction expired"
- :status "Status"
- :recipient "Recipient"
- :specify-recipient "Specify recipient..."
- :recipient-code "Enter recipient address"
- :recent-recipients "Recent recipients"
- :to "To"
- :from "From"
- :data "Data"
- :got-it "Got it"
- :block "Block"
- :hash "Hash"
- :gas-limit "Gas limit"
- :gas-price "Gas price"
- :gas-used "Gas used"
- :cost-fee "Cost/Fee"
- :nonce "Nonce"
- :confirmations "Confirmations"
- :confirmations-helper-text "Please wait for at least 12 confirmations to make sure your transaction is processed securely"
- :copy-transaction-hash "Copy transaction hash"
- :open-on-etherscan "Open on Etherscan.io"
- :incoming "Incoming"
- :outgoing "Outgoing"
- :pending "Pending"
- :postponed "Postponed"
+ :confirm "Confirm"
+ :transaction "Transaction"
+ :unsigned-transaction-expired "Unsigned transaction expired"
+ :status "Status"
+ :recipient "Recipient"
+ :specify-recipient "Specify recipient..."
+ :recipient-code "Enter recipient address"
+ :recent-recipients "Recent recipients"
+ :to "To"
+ :from "From"
+ :data "Data"
+ :got-it "Got it"
+ :block "Block"
+ :hash "Hash"
+ :gas-limit "Gas limit"
+ :gas-price "Gas price"
+ :gas-used "Gas used"
+ :cost-fee "Cost/Fee"
+ :nonce "Nonce"
+ :confirmations "Confirmations"
+ :confirmations-helper-text "Please wait for at least 12 confirmations to make sure your transaction is processed securely"
+ :copy-transaction-hash "Copy transaction hash"
+ :open-on-etherscan "Open on Etherscan.io"
+ :incoming "Incoming"
+ :outgoing "Outgoing"
+ :pending "Pending"
+ :postponed "Postponed"
;;webview
- :web-view-error "oops, error"
+ :web-view-error "oops, error"
;;testfairy warning
- :testfairy-title "Warning!"
- :testfairy-message "You are using an app installed from a nightly build. For testing purposes this build includes session recording if wifi connection is used, so all your interactions with this app is saved (as video and logs) and might be used by our development team to investigate possible issues. Saved video/logs do not include your passwords. Recording is done only if the app is installed from a nightly build. Nothing is recorded if the app is installed from PlayStore or TestFlight."
+ :testfairy-title "Warning!"
+ :testfairy-message "You are using an app installed from a nightly build. For testing purposes this build includes session recording if wifi connection is used, so all your interactions with this app is saved (as video and logs) and might be used by our development team to investigate possible issues. Saved video/logs do not include your passwords. Recording is done only if the app is installed from a nightly build. Nothing is recorded if the app is installed from PlayStore or TestFlight."
;; wallet
- :wallet "Wallet"
- :wallets "Wallets"
- :your-wallets "Your wallets"
- :main-wallet "Main Wallet"
- :wallet-error "Error loading data"
- :wallet-send "Send"
- :wallet-send-token "Send {{symbol}}"
- :wallet-request "Request"
- :wallet-exchange "Exchange"
- :wallet-asset "Asset"
- :wallet-assets "Assets"
- :wallet-add-asset "Add asset"
- :wallet-total-value "Total value"
- :wallet-settings "Wallet settings"
- :wallet-manage-assets "Manage Assets"
- :signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase"
- :wallet-insufficient-funds "Insufficient funds"
- :receive "Receive"
- :request-qr-legend "Share this code to receive assets"
- :send-request "Send request"
- :send-transaction-request "Send a transaction request"
- :share "Share"
- :eth "ETH"
- :gwei "Gwei"
- :currency "Currency"
- :usd-currency "USD"
- :amount-placeholder "Specify amount..."
- :transactions "Transactions"
- :transaction-details "Transaction details"
- :transaction-failed "Transaction failed"
- :transactions-sign "Sign"
- :transactions-sign-all "Sign all"
- :transactions-sign-transaction "Sign transaction"
- :transactions-sign-later "Sign later"
- :transactions-delete "Delete transaction"
- :transactions-delete-content "Transaction will be removed from 'Unsigned' list"
- :transactions-history "History"
- :transactions-unsigned "Unsigned"
- :transactions-history-empty "No transactions in your history yet"
- :transactions-unsigned-empty "You don't have any unsigned transactions"
- :transactions-filter-title "Filter history"
- :transactions-filter-tokens "Tokens"
- :transactions-filter-type "Type"
- :transactions-filter-select-all "Select all"
- :view-transaction-details "View transaction details"
- :transaction-description "Please wait for at least 12 confirmations to make sure your transaction is processed securely"
- :transaction-sent "Transaction sent"
- :transaction-moved-text "The transaction will remain in the 'Unsigned' list for the next 5 mins"
- :transaction-moved-title "Transaction moved"
- :sign-later-title "Sign transaction later?"
- :sign-later-text "Check the transaction history to sign this transaction"
- :not-applicable "Not applicable for unsigned transactions"
- :send-transaction "Send transaction"
- :new-request "New request"
- :request-transaction "Request transaction"
- :receive-transaction "Receive transaction"
- :new-transaction "New Transaction"
- :transaction-history "Transaction History"
+ :wallet "Wallet"
+ :wallets "Wallets"
+ :your-wallets "Your wallets"
+ :main-wallet "Main Wallet"
+ :wallet-error "Error loading data"
+ :wallet-send "Send"
+ :wallet-send-token "Send {{symbol}}"
+ :wallet-request "Request"
+ :wallet-exchange "Exchange"
+ :wallet-asset "Asset"
+ :wallet-assets "Assets"
+ :wallet-add-asset "Add asset"
+ :wallet-total-value "Total value"
+ :wallet-settings "Wallet settings"
+ :wallet-manage-assets "Manage Assets"
+ :signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase"
+ :wallet-insufficient-funds "Insufficient funds"
+ :receive "Receive"
+ :request-qr-legend "Share this code to receive assets"
+ :send-request "Send request"
+ :send-transaction-request "Send a transaction request"
+ :share "Share"
+ :eth "ETH"
+ :gwei "Gwei"
+ :currency "Currency"
+ :usd-currency "USD"
+ :amount-placeholder "Specify amount..."
+ :transactions "Transactions"
+ :transaction-details "Transaction details"
+ :transaction-failed "Transaction failed"
+ :transactions-sign "Sign"
+ :transactions-sign-all "Sign all"
+ :transactions-sign-transaction "Sign transaction"
+ :transactions-sign-later "Sign later"
+ :transactions-delete "Delete transaction"
+ :transactions-delete-content "Transaction will be removed from 'Unsigned' list"
+ :transactions-history "History"
+ :transactions-unsigned "Unsigned"
+ :transactions-history-empty "No transactions in your history yet"
+ :transactions-unsigned-empty "You don't have any unsigned transactions"
+ :transactions-filter-title "Filter history"
+ :transactions-filter-tokens "Tokens"
+ :transactions-filter-type "Type"
+ :transactions-filter-select-all "Select all"
+ :view-transaction-details "View transaction details"
+ :transaction-description "Please wait for at least 12 confirmations to make sure your transaction is processed securely"
+ :transaction-sent "Transaction sent"
+ :transaction-moved-text "The transaction will remain in the 'Unsigned' list for the next 5 mins"
+ :transaction-moved-title "Transaction moved"
+ :sign-later-title "Sign transaction later?"
+ :sign-later-text "Check the transaction history to sign this transaction"
+ :not-applicable "Not applicable for unsigned transactions"
+ :send-transaction "Send transaction"
+ :new-request "New request"
+ :request-transaction "Request transaction"
+ :receive-transaction "Receive transaction"
+ :new-transaction "New Transaction"
+ :transaction-history "Transaction History"
;; Wallet Send
- :wallet-choose-recipient "Choose Recipient"
- :wallet-choose-from-contacts "Choose From Contacts"
- :wallet-address-from-clipboard "Use Address From Clipboard"
- :wallet-invalid-address "Invalid address: \n {{data}}"
- :wallet-invalid-chain-id "Network does not match: \n {{data}} but current chain is {{chain}}"
- :wallet-browse-photos "Browse Photos"
- :wallet-advanced "Advanced"
- :wallet-transaction-fee "Transaction Fee"
- :wallet-transaction-fee-details "Gas limit is the amount of gas to send with your transaction. Increasing this number will not get your transaction processed faster"
- :wallet-transaction-total-fee "Total Fee"
- :validation-amount-invalid-number "Amount is not a valid number"
- :validation-amount-is-too-precise "Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)"
- :scan-qr-code "Scan a QR code with a wallet address"
- :reset-default "Reset to default"
-
-
+ :wallet-choose-recipient "Choose Recipient"
+ :wallet-choose-from-contacts "Choose From Contacts"
+ :wallet-address-from-clipboard "Use Address From Clipboard"
+ :wallet-invalid-address "Invalid address: \n {{data}}"
+ :wallet-invalid-chain-id "Network does not match: \n {{data}} but current chain is {{chain}}"
+ :wallet-browse-photos "Browse Photos"
+ :wallet-advanced "Advanced"
+ :wallet-transaction-fee "Transaction Fee"
+ :wallet-transaction-fee-details "Gas limit is the amount of gas to send with your transaction. Increasing this number will not get your transaction processed faster"
+ :wallet-transaction-total-fee "Total Fee"
+ :validation-amount-invalid-number "Amount is not a valid number"
+ :validation-amount-is-too-precise "Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)"
+ :scan-qr-code "Scan a QR code with a wallet address"
+ :reset-default "Reset to default"
;; network settings
- :new-network "New network"
- :add-network "Add network"
- :add-new-network "Add new network"
- :add-wnode "Add mailserver"
- :existing-networks "Existing networks"
+ :new-network "New network"
+ :add-network "Add network"
+ :add-new-network "Add new network"
+ :add-wnode "Add mailserver"
+ :existing-networks "Existing networks"
;; TODO(dmitryn): come up with better description/naming. Suggested namings: Mailbox and Master Node
- :existing-wnodes "Existing mailservers"
- :add-json-file "Add a JSON file"
- :paste-json-as-text "Paste JSON as text"
- :paste-json "Paste JSON"
- :specify-rpc-url "Specify a RPC URL"
- :edit-network-config "Edit network config"
- :connected "Connected"
- :process-json "Process JSON"
- :error-processing-json "Error processing JSON"
- :rpc-url "RPC URL"
- :network "Network"
- :remove-network "Remove network"
- :network-settings "Network settings"
- :offline-messaging-settings "Offline messages settings"
- :edit-network-warning "Be careful, editing the network data may disable this network for you"
- :connecting-requires-login "Connecting to another network requires login"
- :close-app-title "Warning!"
- :close-app-content "The app will stop and close. When you reopen it, the selected network will be used"
- :close-app-button "Confirm"
- :connect-wnode-content "Connect to {{name}}?"
+ :existing-wnodes "Existing mailservers"
+ :add-json-file "Add a JSON file"
+ :paste-json-as-text "Paste JSON as text"
+ :paste-json "Paste JSON"
+ :specify-rpc-url "Specify a RPC URL"
+ :edit-network-config "Edit network config"
+ :connected "Connected"
+ :process-json "Process JSON"
+ :error-processing-json "Error processing JSON"
+ :rpc-url "RPC URL"
+ :network "Network"
+ :remove-network "Remove network"
+ :network-settings "Network settings"
+ :offline-messaging-settings "Offline messages settings"
+ :edit-network-warning "Be careful, editing the network data may disable this network for you"
+ :connecting-requires-login "Connecting to another network requires login"
+ :close-app-title "Warning!"
+ :close-app-content "The app will stop and close. When you reopen it, the selected network will be used"
+ :close-app-button "Confirm"
+ :connect-wnode-content "Connect to {{name}}?"
;; browser
- :browser "Browser"
- :enter-dapp-url "Enter a ÐApp URL"
- :dapp "ÐApp"
- :selected "Selected"
- :selected-dapps "Selected ÐApps"})
+ :browser "Browser"
+ :enter-dapp-url "Enter a ÐApp URL"
+ :dapp "ÐApp"
+ :selected "Selected"
+ :selected-dapps "Selected ÐApps"})
diff --git a/src/status_im/ui/components/colors.cljs b/src/status_im/ui/components/colors.cljs
index 00a8a01202..4611344861 100644
--- a/src/status_im/ui/components/colors.cljs
+++ b/src/status_im/ui/components/colors.cljs
@@ -11,6 +11,7 @@
(def gray-icon "#6e777e") ;; Used for forward icon in accounts
(def gray-light "#e8ebec") ;; Used as divider color
(def gray-lighter "#eef2f5") ;; Used as a background or shadow
+(def gray-border "#ececf0")
(def blue "#4360df") ;; Used as main wallet color, and ios home add button
(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions
(def red-light "#ffe5ea") ;; error tooltip
diff --git a/src/status_im/ui/components/common/common.cljs b/src/status_im/ui/components/common/common.cljs
index 0c795a4af9..d611cb89e5 100644
--- a/src/status_im/ui/components/common/common.cljs
+++ b/src/status_im/ui/components/common/common.cljs
@@ -88,3 +88,16 @@
:style styles/button-label}
label]]])
+(defn counter
+ ([value] (counter nil value))
+ ([{:keys [size] :or {size 18}} value]
+ [react/view {:style (styles/counter-container size)}
+ [react/text {:style (styles/counter-label size)}
+ value]]))
+
+(defn image-contain
+ ([source] (image-contain nil source))
+ ([{:keys [style]} source]
+ [react/view {:style (merge styles/image-contain
+ style)}
+ [react/image {:source source :resizeMode :contain :style styles/image-contain-image}]]))
\ No newline at end of file
diff --git a/src/status_im/ui/components/common/styles.cljs b/src/status_im/ui/components/common/styles.cljs
index a175a69bd5..4f7dcb6b51 100644
--- a/src/status_im/ui/components/common/styles.cljs
+++ b/src/status_im/ui/components/common/styles.cljs
@@ -148,3 +148,28 @@
:letter-spacing -0.2
:text-align :center
:color colors/blue})
+
+(defn counter-container [size]
+ {:width size
+ :height size
+ :border-radius (/ size 2)
+ :background-color colors/blue
+ :align-items :center
+ :justify-content :center})
+
+(defn counter-label [size]
+ {:font-size (/ size 2)
+ :letter-spacing -0.2
+ :text-align :center
+ :color colors/white})
+
+(def image-contain
+ {:flex-direction :row
+ :flex 1
+ :align-items :center
+ :justify-content :center
+ :flex-wrap :wrap})
+
+(def image-contain-image
+ {:flex-direction :row
+ :flex 1})
diff --git a/src/status_im/ui/components/react.cljs b/src/status_im/ui/components/react.cljs
index 1369d7b536..c39745af4e 100644
--- a/src/status_im/ui/components/react.cljs
+++ b/src/status_im/ui/components/react.cljs
@@ -46,6 +46,7 @@
(def text-class (get-class "Text"))
(def text-input-class (get-class "TextInput"))
(def image (get-class "Image"))
+(def switch (get-class "Switch"))
(def check-box (get-class "CheckBox"))
(def touchable-without-feedback (get-class "TouchableWithoutFeedback"))
diff --git a/src/status_im/ui/components/text_input/styles.cljs b/src/status_im/ui/components/text_input/styles.cljs
index 8a9f4d3467..77418229ae 100644
--- a/src/status_im/ui/components/text_input/styles.cljs
+++ b/src/status_im/ui/components/text_input/styles.cljs
@@ -21,7 +21,7 @@
:color colors/black
:padding 0})
-(def error
- {:bottom-value -20
+(defn error [label?]
+ {:bottom-value (if label? -20 0)
:color colors/red-light
:font-size 12})
\ No newline at end of file
diff --git a/src/status_im/ui/components/text_input/view.cljs b/src/status_im/ui/components/text_input/view.cljs
index 2be1dccbc6..57686104c3 100644
--- a/src/status_im/ui/components/text_input/view.cljs
+++ b/src/status_im/ui/components/text_input/view.cljs
@@ -6,8 +6,9 @@
(defn text-input-with-label [{:keys [label error style height] :as props}]
[react/view
- [react/text {:style styles/label}
- label]
+ (when label
+ [react/text {:style styles/label}
+ label])
[react/view {:style (styles/input-container height)}
[react/text-input
(merge
@@ -17,4 +18,4 @@
:auto-capitalize :none}
(dissoc props :style :height))]]
(when error
- [tooltip/tooltip error styles/error])])
+ [tooltip/tooltip error (styles/error label)])])
diff --git a/src/status_im/ui/components/toolbar/styles.cljs b/src/status_im/ui/components/toolbar/styles.cljs
index a410082bb8..f79f1adfad 100644
--- a/src/status_im/ui/components/toolbar/styles.cljs
+++ b/src/status_im/ui/components/toolbar/styles.cljs
@@ -84,3 +84,8 @@
;;TODO(goranjovic) - Breaks the toolbar title into new line on smaller screens
;;e.g. see Discover > Popular hashtags on iPhone 5s
(def ios-content-item {:position :absolute :right 40 :left 40})
+
+(def counter-container
+ {:position :absolute
+ :top 19
+ :right 2})
diff --git a/src/status_im/ui/components/toolbar/view.cljs b/src/status_im/ui/components/toolbar/view.cljs
index b059083c9e..79a070bd7a 100644
--- a/src/status_im/ui/components/toolbar/view.cljs
+++ b/src/status_im/ui/components/toolbar/view.cljs
@@ -1,4 +1,5 @@
(ns status-im.ui.components.toolbar.view
+ (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.icons.vector-icons :as vector-icons]
@@ -8,7 +9,8 @@
[status-im.ui.components.toolbar.actions :as actions]
[status-im.ui.components.toolbar.styles :as styles]
[status-im.utils.platform :as platform]
- [status-im.utils.core :as utils]))
+ [status-im.utils.core :as utils]
+ [status-im.ui.components.common.common :as components.common]))
;; Navigation item
@@ -26,6 +28,14 @@
[nav-item (merge {:style styles/nav-item-button} props)
[vector-icons/icon icon icon-opts]])
+(defview nav-button-with-count [props]
+ (letsubs [unread-messages-number [:get-chats-unread-messages-number]]
+ [react/view
+ [nav-button props]
+ (when (pos? unread-messages-number)
+ [react/view styles/counter-container
+ [components.common/counter unread-messages-number]])]))
+
(defn nav-text
([text] (nav-text nil text))
([{:keys [handler] :as props} text]
@@ -41,6 +51,8 @@
(def default-nav-back [nav-button actions/default-back])
+(def nav-back-count [nav-button-with-count actions/default-back])
+
(defn default-done
"Renders a touchable icon on Android or a label or iOS."
[{:keys [icon] :as props}]
diff --git a/src/status_im/ui/screens/accounts/db.cljs b/src/status_im/ui/screens/accounts/db.cljs
index fe5da47c53..7eae134fae 100644
--- a/src/status_im/ui/screens/accounts/db.cljs
+++ b/src/status_im/ui/screens/accounts/db.cljs
@@ -28,7 +28,10 @@
(spec/def :account/wnode (spec/nilable string?))
(spec/def :account/settings (spec/nilable (spec/map-of keyword? any?)))
(spec/def :account/signing-phrase :global/not-empty-string)
+(spec/def :account/mnemonic (spec/nilable string?))
(spec/def :account/sharing-usage-data? (spec/nilable boolean?))
+(spec/def :account/dev-mode? (spec/nilable boolean?))
+(spec/def :account/seed-backed-up? (spec/nilable boolean?))
(spec/def :accounts/account (allowed-keys
:req-un [:account/name :account/address :account/public-key
@@ -37,7 +40,8 @@
:account/updates-private-key :account/updates-public-key
:account/email :account/signed-up? :account/network
:account/networks :account/settings :account/wnode
- :account/last-sign-in :account/sharing-usage-data?]))
+ :account/last-sign-in :account/sharing-usage-data? :account/dev-mode?
+ :account/seed-backed-up? :account/mnemonic]))
(spec/def :accounts/accounts (spec/nilable (spec/map-of :account/address :accounts/account)))
diff --git a/src/status_im/ui/screens/accounts/events.cljs b/src/status_im/ui/screens/accounts/events.cljs
index 63de61bb6b..eac8f0bbea 100644
--- a/src/status_im/ui/screens/accounts/events.cljs
+++ b/src/status_im/ui/screens/accounts/events.cljs
@@ -119,6 +119,7 @@
:updates-private-key (:private keypair)
:photo-path (identicon pubkey)
:signing-phrase signing-phrase
+ :mnemonic mnemonic
:settings {:wallet {:visible-tokens {:testnet #{:STT} :mainnet #{:SNT}}}}}]
(log/debug "account-created")
(when-not (str/blank? pubkey)
@@ -158,13 +159,18 @@
"Takes effects (containing :db) + new account fields, adds all effects necessary for account update."
[{{:accounts/keys [accounts current-account-id] :as db} :db :as fx} new-account-fields]
(let [current-account (get accounts current-account-id)
- new-account (merge current-account new-account-fields)]
- (-> fx
- (assoc-in [:db :accounts/accounts current-account-id] new-account)
- (assoc ::save-account new-account
- ::broadcast-account-update (merge (select-keys db [:current-public-key :web3])
- (select-keys new-account [:name :photo-path :status
- :updates-public-key :updates-private-key]))))))
+ new-account (merge current-account new-account-fields)
+ broadcast-fields [:name :photo-path :status
+ :updates-public-key :updates-private-key]]
+ (cond-> fx
+ true
+ (assoc-in [:db :accounts/accounts current-account-id] new-account)
+ true
+ (assoc ::save-account new-account)
+
+ (seq (clojure.set/intersection (set (keys new-account-fields)) (set broadcast-fields)))
+ (assoc ::broadcast-account-update (merge (select-keys db [:current-public-key :web3])
+ (select-keys new-account broadcast-fields))))))
(handlers/register-handler-fx
:account-update-keys
@@ -210,3 +216,8 @@
:reset-account-creation
(fn [{db :db} _]
{:db (update db :accounts/create assoc :step :enter-password :password nil :password-confirm nil :error nil)}))
+
+(handlers/register-handler-fx
+ :switch-dev-mode
+ (fn [{db :db} [_ dev-mode]]
+ (account-update {:db db} {:dev-mode? dev-mode})))
\ No newline at end of file
diff --git a/src/status_im/ui/screens/accounts/recover/events.cljs b/src/status_im/ui/screens/accounts/recover/events.cljs
index 36d70f742e..e54e8eedae 100644
--- a/src/status_im/ui/screens/accounts/recover/events.cljs
+++ b/src/status_im/ui/screens/accounts/recover/events.cljs
@@ -39,6 +39,7 @@
:photo-path (identicon/identicon public-key)
:updates-public-key public
:updates-private-key private
+ :mnemonic ""
:signed-up? true
:signing-phrase phrase}]
(when-not (string/blank? public-key)
diff --git a/src/status_im/ui/screens/browser/styles.cljs b/src/status_im/ui/screens/browser/styles.cljs
index 6711202632..9fcd449163 100644
--- a/src/status_im/ui/screens/browser/styles.cljs
+++ b/src/status_im/ui/screens/browser/styles.cljs
@@ -54,10 +54,10 @@
:background-color colors/gray-lighter
:padding-horizontal 12
:android {:align-items :flex-start
- :margin-left (if show-actions 66 18)
+ :margin-left (if show-actions 66 20)
:padding-bottom 6}
:ios {:align-items :center
- :margin-horizontal 12}})
+ :margin-horizontal 15}})
(defstyle url-input
{:flex 1
@@ -67,4 +67,4 @@
(def toolbar-content-dapp
{:flex-direction :row
- :margin-horizontal 10})
+ :margin-horizontal 15})
\ No newline at end of file
diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs
index 98f9d4d71d..561bd30676 100644
--- a/src/status_im/ui/screens/browser/views.cljs
+++ b/src/status_im/ui/screens/browser/views.cljs
@@ -5,7 +5,6 @@
[status-im.ui.screens.browser.styles :as styles]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar.view]
- [status-im.chat.views.toolbar-content :as toolbar-content]
[status-im.ui.components.webview-bridge :as components.webview-bridge]
[status-im.utils.js-resources :as js-res]
[status-im.ui.components.react :as components]
@@ -16,32 +15,34 @@
(views/defview toolbar-content-dapp [contact-identity]
(views/letsubs [contact [:contact-by-identity contact-identity]]
- [react/view styles/toolbar-content-dapp
- [chat-icon.screen/dapp-icon-browser contact 36]
- [react/view styles/dapp-name
- [react/text {:style styles/dapp-name-text
- :number-of-lines 1
- :font :toolbar-title
- :accessibility-label :dapp-name-text}
- (:name contact)]
- [react/text {:style styles/dapp-text}
- (i18n/label :t/dapp)]]]))
+ [react/view
+ [react/view styles/toolbar-content-dapp
+ [chat-icon.screen/dapp-icon-browser contact 36]
+ [react/view styles/dapp-name
+ [react/text {:style styles/dapp-name-text
+ :number-of-lines 1
+ :font :toolbar-title
+ :accessibility-label :dapp-name-text}
+ (:name contact)]
+ [react/text {:style styles/dapp-text}
+ (i18n/label :t/dapp)]]]]))
(defn toolbar-content [{:keys [url] :as browser}]
(let [url-text (atom nil)]
- [react/view (styles/toolbar-content false)
- [react/text-input {:on-change-text #(reset! url-text %)
- :on-submit-editing #(re-frame/dispatch [:update-browser (assoc browser :url @url-text)])
- :auto-focus (not url)
- :placeholder (i18n/label :t/enter-url)
- :auto-capitalize :none
- :auto-correct false
- :default-value url
- :style styles/url-input}]
- ;;TODO .reload doesn't work, implement later
- #_[react/touchable-highlight {:on-press #(when @webview (.reload @webview))}
- [react/view
- [vector-icons/icon :icons/refresh]]]]))
+ [react/view
+ [react/view (styles/toolbar-content false)
+ [react/text-input {:on-change-text #(reset! url-text %)
+ :on-submit-editing #(re-frame/dispatch [:update-browser (assoc browser :url @url-text)])
+ :auto-focus (not url)
+ :placeholder (i18n/label :t/enter-url)
+ :auto-capitalize :none
+ :auto-correct false
+ :default-value url
+ :style styles/url-input}]
+ ;;TODO .reload doesn't work, implement later
+ #_[react/touchable-highlight {:on-press #(when @webview (.reload @webview))}
+ [react/view
+ [vector-icons/icon :icons/refresh]]]]]))
(defn web-view-error []
(reagent/as-element
@@ -54,7 +55,7 @@
[components/activity-indicator {:animating true}]]))
(defn on-navigation-change [event browser]
- (let [{:strs [loading url title canGoBack canGoForward]} (js->clj event)]
+ (let [{:strs [url title canGoBack canGoForward]} (js->clj event)]
(when-not (= "about:blank" url)
(re-frame/dispatch [:update-browser (assoc browser :url url :name title)]))
(re-frame/dispatch [:update-browser-options {:can-go-back? canGoBack :can-go-forward? canGoForward}])))
@@ -64,14 +65,15 @@
{:keys [dapp? contact url] :as browser} [:get-current-browser]
{:keys [can-go-back? can-go-forward?]} [:get :browser/options]
extra-js [:web-view-extra-js]
- rpc-url [:get :rpc-url]]
+ rpc-url [:get :rpc-url]
+ unread-messages-number [:get-chats-unread-messages-number]]
[react/keyboard-avoiding-view styles/browser
[status-bar/status-bar]
[toolbar.view/toolbar {}
- toolbar.view/default-nav-back
+ toolbar.view/nav-back-count
(if dapp?
- [toolbar-content-dapp contact]
- [toolbar-content browser])]
+ [toolbar-content-dapp contact unread-messages-number]
+ [toolbar-content browser unread-messages-number])]
(if url
[components.webview-bridge/webview-bridge
{:ref #(reset! webview %)
diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs
index 9ee824b797..cf21f090cd 100644
--- a/src/status_im/ui/screens/db.cljs
+++ b/src/status_im/ui/screens/db.cljs
@@ -146,10 +146,11 @@
:accounts/current-account-id
:accounts/recover
:accounts/login
- :my-profile/drawer
:my-profile/profile
:my-profile/default-name
:my-profile/editing?
+ :my-profile/advanced?
+ :my-profile/seed
:group-chat-profile/profile
:group-chat-profile/editing?
:networks/selected-network
diff --git a/src/status_im/ui/screens/home/views/inner_item.cljs b/src/status_im/ui/screens/home/views/inner_item.cljs
index f584895cad..b58dbe4e28 100644
--- a/src/status_im/ui/screens/home/views/inner_item.cljs
+++ b/src/status_im/ui/screens/home/views/inner_item.cljs
@@ -12,7 +12,8 @@
[status-im.utils.gfycat.core :as gfycat]
[status-im.constants :as const]
[status-im.ui.components.icons.vector-icons :as vector-icons]
- [status-im.ui.components.chat-icon.screen :as chat-icon.screen]))
+ [status-im.ui.components.chat-icon.screen :as chat-icon.screen]
+ [status-im.ui.components.common.common :as components.common]))
(defn message-content-text [{:keys [content] :as message}]
[react/view styles/last-message-container
@@ -58,10 +59,7 @@
(defview unviewed-indicator [chat-id]
(letsubs [unviewed-messages-count [:unviewed-messages-count chat-id]]
(when (pos? unviewed-messages-count)
- [react/view styles/new-messages-container
- [react/text {:style styles/new-messages-text
- :font :medium}
- unviewed-messages-count]])))
+ [components.common/counter {:size 22} unviewed-messages-count])))
(defn chat-list-item-name [name group-chat? public? public-key]
(let [private-group? (and group-chat? (not public?))
@@ -89,7 +87,6 @@
(letsubs [last-message [:get-last-message chat-id]]
(let [name (or (i18n/get-contact-translated chat-id :name name)
(gfycat/generate-gfy public-key))]
- [react/view
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to-chat chat-id])}
[react/view styles/chat-container
[react/view styles/chat-icon-container
@@ -103,7 +100,7 @@
[message-timestamp last-message]])]
[react/view styles/item-lower-container
[message-content-text last-message]
- [unviewed-indicator chat-id]]]]]])))
+ [unviewed-indicator chat-id]]]]])))
(defview home-list-browser-item-inner-view [{:keys [browser-id name url dapp? contact] :as browser}]
(letsubs [contact' [:contact-by-identity contact]]
diff --git a/src/status_im/ui/screens/main_tabs/styles.cljs b/src/status_im/ui/screens/main_tabs/styles.cljs
index 856056f12a..f17110e0f3 100644
--- a/src/status_im/ui/screens/main_tabs/styles.cljs
+++ b/src/status_im/ui/screens/main_tabs/styles.cljs
@@ -27,4 +27,11 @@
styles/color-gray4)})
(defn tab-icon [active?]
- {:color (if active? styles/color-blue4 styles/color-gray4)})
\ No newline at end of file
+ {:color (if active? styles/color-blue4 styles/color-gray4)})
+
+(def counter-container
+ {:position :absolute
+ :top 4})
+
+(def counter
+ {:margin-left 18})
\ No newline at end of file
diff --git a/src/status_im/ui/screens/main_tabs/views.cljs b/src/status_im/ui/screens/main_tabs/views.cljs
index 6cc1cfe841..e3eb551215 100644
--- a/src/status_im/ui/screens/main_tabs/views.cljs
+++ b/src/status_im/ui/screens/main_tabs/views.cljs
@@ -9,51 +9,60 @@
[status-im.ui.screens.home.views :as home]
[status-im.ui.screens.wallet.views :as wallet]
[status-im.ui.screens.main-tabs.styles :as styles]
- [status-im.ui.screens.profile.user.views :as profile.user]))
+ [status-im.ui.screens.profile.user.views :as profile.user]
+ [status-im.ui.components.common.common :as components.common]))
(def tabs-list-data
[{:view-id :home
:content {:title (i18n/label :t/home)
:icon-inactive :icons/home
:icon-active :icons/home-active}
+ :count-subscription :get-chats-unread-messages-number
:accessibility-label :home-tab-button}
{:view-id :wallet
:content {:title (i18n/label :t/wallet)
:icon-inactive :icons/wallet
:icon-active :icons/wallet-active}
+ :count-subscription :get-wallet-unread-messages-number
:accessibility-label :wallet-tab-button}
{:view-id :my-profile
:content {:title (i18n/label :t/profile)
:icon-inactive :icons/profile
:icon-active :icons/profile-active}
+ :count-subscription :get-profile-unread-messages-number
:accessibility-label :profile-tab-button}])
(defn- tab-content [{:keys [title icon-active icon-inactive]}]
- (fn [active?]
+ (fn [active? count]
[react/view {:style styles/tab-container}
(let [icon (if active? icon-active icon-inactive)]
[react/view
[vector-icons/icon icon (styles/tab-icon active?)]])
[react/view
[react/text {:style (styles/tab-title active?)}
- title]]]))
+ title]]
+ (when (pos? count)
+ [react/view styles/counter-container
+ [react/view styles/counter
+ [components.common/counter count]]])]))
(def tabs-list (map #(update % :content tab-content) tabs-list-data))
-(defn- tab [view-id content active? accessibility-label]
- [react/touchable-highlight
- (cond-> {:style common.styles/flex
- :disabled active?
- :on-press #(re-frame/dispatch [:navigate-to-tab view-id])}
- accessibility-label
- (assoc :accessibility-label accessibility-label))
- [react/view
- [content active?]]])
+(views/defview tab [view-id content active? accessibility-label count-subscription]
+ (views/letsubs [count [count-subscription]]
+ [react/touchable-highlight
+ (cond-> {:style common.styles/flex
+ :disabled active?
+ :on-press #(re-frame/dispatch [:navigate-to-tab view-id])}
+ accessibility-label
+ (assoc :accessibility-label accessibility-label))
+ [react/view
+ [content active? count]]]))
(defn tabs [current-view-id]
[react/view {:style styles/tabs-container}
- (for [{:keys [content view-id accessibility-label]} tabs-list]
- ^{:key view-id} [tab view-id content (= view-id current-view-id) accessibility-label])])
+ (for [{:keys [content view-id accessibility-label count-subscription]} tabs-list]
+ ^{:key view-id} [tab view-id content (= view-id current-view-id) accessibility-label count-subscription])])
(views/defview main-tabs []
(views/letsubs [view-id [:get :view-id]]
diff --git a/src/status_im/ui/screens/profile/components/views.cljs b/src/status_im/ui/screens/profile/components/views.cljs
index 47586f18e5..1acd1595b0 100644
--- a/src/status_im/ui/screens/profile/components/views.cljs
+++ b/src/status_im/ui/screens/profile/components/views.cljs
@@ -6,7 +6,6 @@
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.screens.profile.components.styles :as styles]
[status-im.ui.components.common.common :as common]
- [status-im.ui.components.styles :as components.styles]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.colors :as colors]
[clojure.string :as string]))
@@ -63,7 +62,8 @@
[react/text {:style styles/settings-title}
title])
-(defn settings-item [label-kw value action-fn active? & [accessibility-label]]
+(defn settings-item [{:keys [label-kw value action-fn active? accessibility-label icon-content]
+ :or {value "" active? true}}]
[react/touchable-highlight
(cond-> {:on-press action-fn
:disabled (not active?)}
@@ -79,5 +79,17 @@
:number-of-lines 1
:uppercase? true}
value])]
- (when active?
- [vector-icons/icon :icons/forward {:color colors/gray}])]])
+ (if icon-content
+ icon-content
+ (when active?
+ [vector-icons/icon :icons/forward {:color colors/gray}]))]])
+
+(defn settings-switch-item [{:keys [label-kw value action-fn active?] :or {active? true}}]
+ [react/view styles/settings-item
+ [react/view styles/settings-item-text-wrapper
+ [react/text {:style styles/settings-item-text}
+ (i18n/label label-kw)]]
+ [react/switch {:on-tint-color colors/blue
+ :value value
+ :on-value-change action-fn
+ :disabled (not active?)}]])
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/db.cljs b/src/status_im/ui/screens/profile/db.cljs
index 65a7e9cc83..57c5e86596 100644
--- a/src/status_im/ui/screens/profile/db.cljs
+++ b/src/status_im/ui/screens/profile/db.cljs
@@ -1,13 +1,10 @@
(ns status-im.ui.screens.profile.db
- (:require-macros [status-im.utils.db :refer [allowed-keys]])
(:require [cljs.spec.alpha :as spec]
[clojure.string :as string]
[status-im.chat.constants :as chat.constants]
[status-im.constants :as constants]
[status-im.utils.homoglyph :as homoglyph]))
-(def account-profile-keys [:name :photo-path :status])
-
(defn correct-name? [username]
(when-let [username (some-> username (string/trim))]
(every? false?
@@ -15,11 +12,6 @@
(homoglyph/matches username constants/console-chat-id)
(string/includes? username chat.constants/command-char)])))
-(defn correct-email? [email]
- (let [pattern #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"]
- (or (string/blank? email)
- (and (string? email) (re-matches pattern email)))))
-
(defn base64-encoded-image-path? [photo-path]
(or (string/starts-with? photo-path "data:image/jpeg;base64,")
(string/starts-with? photo-path "data:image/png;base64,")))
@@ -28,9 +20,9 @@
(spec/def :profile/status (spec/nilable string?))
(spec/def :profile/photo-path (spec/nilable base64-encoded-image-path?))
-;; EDIT PROFILE
-(spec/def :my-profile/default-name string?)
+(spec/def :my-profile/default-name (spec/nilable string?))
+(spec/def :my-profile/editing? (spec/nilable boolean?))
+(spec/def :my-profile/advanced? (spec/nilable boolean?))
+(spec/def :my-profile/seed (spec/nilable map?))
(spec/def :my-profile/profile (spec/keys :opt-un [::name :profile/status :profile/photo-path
::edit-status? ::valid-name?]))
-(spec/def :my-profile/drawer (spec/keys :opt-un [::name :profile/status
- ::edit-status? ::valid-name?]))
diff --git a/src/status_im/ui/screens/profile/events.cljs b/src/status_im/ui/screens/profile/events.cljs
index 78ab2e9f72..697d01c84e 100644
--- a/src/status_im/ui/screens/profile/events.cljs
+++ b/src/status_im/ui/screens/profile/events.cljs
@@ -34,7 +34,7 @@
(as-> fx
(merge fx (input-events/select-chat-input-command (:db fx) send-command nil true)))))))
-(defn get-current-account [{:keys [:accounts/current-account-id] :as db}]
+(defn get-current-account [{:accounts/keys [current-account-id] :as db}]
(get-in db [:accounts/accounts current-account-id]))
(defn valid-name? [name]
@@ -61,15 +61,7 @@
(get-in db [:accounts/accounts current-account-id :name]))))
(defn clear-profile [fx]
- (update fx :db dissoc :my-profile/profile :my-profile/drawer :my-profile/default-name :my-profile/editing?))
-
-(handlers/register-handler-fx
- :my-profile.drawer/save-name
- (fn [{:keys [db now]} _]
- (let [cleaned-name (clean-name db :my-profile/drawer)]
- (-> (clear-profile {:db db})
- (accounts-events/account-update {:name cleaned-name
- :last-updated now})))))
+ (update fx :db dissoc :my-profile/profile :my-profile/default-name :my-profile/editing?))
(handlers/register-handler-fx
:my-profile/start-editing-profile
@@ -99,3 +91,23 @@
(fn [{:keys [db]} _]
(-> {:db db}
(update :db dissoc :group-chat-profile/editing?))))
+
+(handlers/register-handler-fx
+ :my-profile/enter-two-random-words
+ (fn [{:keys [db]} []]
+ (let [{:keys [mnemonic]} (get-current-account db)
+ shuffled-mnemonic (shuffle (map-indexed vector (clojure.string/split mnemonic #" ")))]
+ {:db (assoc db :my-profile/seed {:step :first-word
+ :first-word (first shuffled-mnemonic)
+ :second-word (second shuffled-mnemonic)})})))
+
+(handlers/register-handler-fx
+ :my-profile/set-step
+ (fn [{:keys [db]} [_ step]]
+ {:db (update db :my-profile/seed assoc :step step :error nil :word nil)}))
+
+(handlers/register-handler-fx
+ :my-profile/finish
+ (fn [{:keys [db]} _]
+ (-> {:db (update db :my-profile/seed assoc :step :finish :error nil :word nil)}
+ (accounts-events/account-update {:seed-backed-up? true}))))
diff --git a/src/status_im/ui/screens/profile/navigation.cljs b/src/status_im/ui/screens/profile/navigation.cljs
index ecbf3bed01..ee0ee9bebd 100644
--- a/src/status_im/ui/screens/profile/navigation.cljs
+++ b/src/status_im/ui/screens/profile/navigation.cljs
@@ -9,3 +9,6 @@
:source source
:value value})))
+(defmethod navigation/preload-data! :backup-seed
+ [db]
+ (assoc db :my-profile/seed {:step :intro}))
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/seed/styles.cljs b/src/status_im/ui/screens/profile/seed/styles.cljs
new file mode 100644
index 0000000000..66d68fe270
--- /dev/null
+++ b/src/status_im/ui/screens/profile/seed/styles.cljs
@@ -0,0 +1,154 @@
+(ns status-im.ui.screens.profile.seed.styles
+ (:require [status-im.ui.components.colors :as colors]))
+
+(def intro-container
+ {:flex 1
+ :align-items :center
+ :margin-horizontal 26})
+
+(def intro-image
+ {:padding-vertical 25})
+
+(def intro-text
+ {:text-align :center
+ :font-size 22
+ :font-weight :bold
+ :line-height 28
+ :letter-spacing -0.3})
+
+(def intro-description
+ {:margin-top 8
+ :font-size 14
+ :line-height 21
+ :letter-spacing -0.2
+ :text-align :center
+ :color colors/gray})
+
+(def intro-button
+ {:flex-direction :row
+ :margin-top 16
+ :margin-bottom 32})
+
+(def six-words-container
+ {:flex 1
+ :padding 15})
+
+(def six-word-row
+ {:flex-direction :row})
+
+(def six-word-num
+ {:opacity 0.4
+ :font-size 15
+ :letter-spacing -0.2})
+
+(def six-words-word
+ {:margin-left 16
+ :font-size 15
+ :letter-spacing -0.2})
+
+(def six-words-separator
+ {:height 12})
+
+(def twelve-words-container
+ {:flex 1
+ :padding 16})
+
+(def twelve-words-label
+ {:font-size 14
+ :line-height 21
+ :letter-spacing -0.2})
+
+(def twelve-words-description
+ {:font-size 14
+ :line-height 21
+ :letter-spacing -0.2})
+
+(def twelve-words-spacer
+ {:flex 1})
+
+(def twelve-words-button-container
+ {:align-items :flex-end})
+
+(def twelve-words-columns
+ {:margin-top 8
+ :margin-bottom 16
+ :flex-direction :row
+ :border-radius 8
+ :background-color colors/white
+ :border-width 1
+ :border-color colors/gray-border})
+
+(def twelve-words-columns-separator
+ {:width 1
+ :background-color colors/gray-border})
+
+(def enter-word-container
+ {:flex 1
+ :padding 16})
+
+(def enter-word-row
+ {:flex-direction :row})
+
+(def enter-word-label
+ {:font-size 14
+ :line-height 21
+ :letter-spacing -0.2})
+
+(def enter-word-n
+ {:margin-left 8
+ :font-size 14
+ :line-height 21
+ :letter-spacing -0.2
+ :color colors/gray})
+
+(def enter-word-n-description
+ {:font-size 14
+ :line-height 21
+ :letter-spacing -0.2
+ :color colors/gray})
+
+(def finish-container
+ {:flex 1
+ :padding-horizontal 24
+ :align-items :center})
+
+(def finish-logo-container
+ {:flex 1
+ :align-items :center
+ :justify-content :center})
+
+(def ok-icon
+ {:color :white
+ :width 41
+ :height 41})
+
+(def finish-label
+ {:font-size 22
+ :font-weight :bold
+ :line-height 30
+ :letter-spacing -0.3
+ :text-align :center})
+
+(def finish-description
+ {:margin-top 8
+ :font-size 14
+ :line-height 20
+ :text-align :center
+ :color colors/gray})
+
+(def finish-button
+ {:flex-direction :row
+ :margin-top 16
+ :margin-bottom 32})
+
+(def backup-seed
+ {:font-weight :bold
+ :font-size 15
+ :letter-spacing -0.2
+ :text-align :center})
+
+(def step-n
+ {:margin-top 5
+ :font-size 14
+ :text-align :center
+ :color colors/gray})
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/seed/views.cljs b/src/status_im/ui/screens/profile/seed/views.cljs
new file mode 100644
index 0000000000..28c05beeff
--- /dev/null
+++ b/src/status_im/ui/screens/profile/seed/views.cljs
@@ -0,0 +1,146 @@
+(ns status-im.ui.screens.profile.seed.views
+ (:require-macros [status-im.utils.views :refer [defview letsubs]])
+ (:require [status-im.ui.components.react :as react]
+ [status-im.ui.components.status-bar.view :as status-bar]
+ [status-im.ui.components.toolbar.view :as toolbar]
+ [status-im.ui.components.toolbar.actions :as actions]
+ [status-im.ui.components.colors :as colors]
+ [status-im.react-native.resources :as resources]
+ [status-im.ui.components.common.common :as components.common]
+ [re-frame.core :as re-frame]
+ [status-im.ui.components.text-input.view :as text-input]
+ [status-im.ui.components.icons.vector-icons :as icons]
+ [status-im.ui.components.common.common :as components.common]
+ [status-im.ui.components.common.styles :as components.common.styles]
+ [clojure.string :as string]
+ [status-im.utils.utils :as utils]
+ [status-im.ui.screens.profile.seed.styles :as styles]
+ [status-im.i18n :as i18n]
+ [status-im.ui.components.styles :as common.styles]))
+
+(def steps-numbers
+ {:intro 1
+ :12-words 1
+ :first-word 2
+ :second-word 3
+ :finish 3})
+
+(defn step-back [step]
+ (case step
+ (:intro :12-words) (re-frame/dispatch [:navigate-back])
+ :first-word (re-frame/dispatch [:my-profile/set-step :12-words])
+ :second-word (re-frame/dispatch [:my-profile/set-step :first-word])))
+
+(defn intro []
+ [react/view {:style styles/intro-container}
+ [components.common/image-contain {:style styles/intro-image}
+ (:lock resources/ui)]
+ [react/text {:style styles/intro-text}
+ (i18n/label :t/your-data-belongs-to-you)]
+ [react/text {:style styles/intro-description}
+ (i18n/label :t/your-data-belongs-to-you-description)]
+ [components.common/button {:style styles/intro-button
+ :on-press #(re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])
+ :label (i18n/label :t/ok-continue)}]])
+
+(defn six-words [words]
+ [react/view {:style styles/six-words-container}
+ (for [[i word] words]
+ ^{:key (str "word" i)}
+ [react/view
+ [react/view {:style styles/six-word-row}
+ [react/text {:style styles/six-word-num}
+ (inc i)]
+ [react/text {:style styles/six-words-word}
+ word]]
+ (when (not= i (first (last words)))
+ [react/view {:style styles/six-words-separator}])])])
+
+(defn twelve-words [{:keys [mnemonic]}]
+ (let [mnemonic-vec (vec (map-indexed vector (clojure.string/split mnemonic #" ")))]
+ [react/view {:style styles/twelve-words-container}
+ [react/text {:style styles/twelve-words-label}
+ (i18n/label :t/your-seed-phrase)]
+ [react/view {:style styles/twelve-words-columns}
+ [six-words (subvec mnemonic-vec 0 6)]
+ [react/view {:style styles/twelve-words-columns-separator}]
+ [six-words (subvec mnemonic-vec 6 12)]]
+ [react/text {:style styles/twelve-words-description}
+ (i18n/label :t/your-seed-phrase-description)]
+ [react/view styles/twelve-words-spacer]
+ [react/view styles/twelve-words-button-container
+ [components.common/bottom-button
+ {:forward? true
+ :on-press #(re-frame/dispatch [:my-profile/enter-two-random-words])}]]]))
+
+(defview input [error]
+ [text-input/text-input-with-label
+ {:placeholder (i18n/label :t/enter-word)
+ :auto-focus true
+ :on-change-text #(re-frame/dispatch [:set-in [:my-profile/seed :word] %])
+ :error error}])
+
+(defn enter-word [step [idx word] error entered-word]
+ ^{:key word}
+ [react/view {:style styles/enter-word-container}
+ [react/view {:style styles/enter-word-row}
+ [react/text {:style styles/enter-word-label}
+ (i18n/label :t/check-your-seed)]
+ [react/text {:style styles/enter-word-n}
+ (i18n/label :t/word-n {:number (inc idx)})]]
+ [input error]
+ [react/text {:style styles/enter-word-n-description}
+ (i18n/label :t/word-n-description {:number (inc idx)})]
+ [react/view styles/twelve-words-spacer]
+ [react/view styles/twelve-words-button-container
+ [components.common/bottom-button
+ {:forward? (not= :second-word step)
+ :label (when (= :second-word step) (i18n/label :t/done))
+ :disabled? (string/blank? entered-word)
+ :on-press (fn [_]
+ (cond (not= word entered-word)
+ (re-frame/dispatch [:set-in [:my-profile/seed :error] (i18n/label :t/wrong-word)])
+
+ (= :first-word step)
+ (re-frame/dispatch [:my-profile/set-step :second-word])
+
+ :else
+ (utils/show-question
+ (i18n/label :t/are-you-sure?)
+ (i18n/label :t/are-you-sure-description)
+ #(re-frame/dispatch [:my-profile/finish]))))}]]])
+
+(defn finish []
+ [react/view {:style styles/finish-container}
+ [react/view {:style styles/finish-logo-container}
+ [react/view {:style (components.common.styles/logo-container 80 true)}
+ [icons/icon :icons/ok styles/ok-icon]]]
+ [react/text {:style styles/finish-label}
+ (i18n/label :t/you-are-all-set)]
+ [react/text {:style styles/finish-description}
+ (i18n/label :t/you-are-all-set-description)]
+ [components.common/button {:style styles/finish-button
+ :on-press #(re-frame/dispatch [:navigate-back])
+ :label (i18n/label :t/ok-got-it)}]])
+
+(defview backup-seed []
+ (letsubs [current-account [:get-current-account]
+ {:keys [step first-word second-word error word]} [:get :my-profile/seed]]
+ [react/keyboard-avoiding-view {:style common.styles/flex}
+ [status-bar/status-bar]
+ [toolbar/toolbar
+ nil
+ (when-not (#{:finish} step)
+ (toolbar/nav-button (actions/back #(step-back step))))
+ [react/view
+ [react/text {:style styles/backup-seed}
+ (i18n/label :t/backup-seed-phrase)]
+ [react/text {:style styles/step-n}
+ (i18n/label :t/step-i-of-n {:step (steps-numbers step) :number 3})]]]
+ [components.common/separator]
+ (case step
+ :intro [intro]
+ :12-words [twelve-words current-account]
+ :first-word [enter-word step first-word error word]
+ :second-word [enter-word step second-word error word]
+ :finish [finish])]))
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/subs.cljs b/src/status_im/ui/screens/profile/subs.cljs
new file mode 100644
index 0000000000..47a795eb4d
--- /dev/null
+++ b/src/status_im/ui/screens/profile/subs.cljs
@@ -0,0 +1,9 @@
+(ns status-im.ui.screens.profile.subs
+ (:require [re-frame.core :refer [reg-sub]]
+ [clojure.string :as string]))
+
+(reg-sub
+ :get-profile-unread-messages-number
+ :<- [:get-current-account]
+ (fn [{:keys [seed-backed-up? mnemonic]}]
+ (if (or seed-backed-up? (string/blank? mnemonic)) 0 1)))
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/user/styles.cljs b/src/status_im/ui/screens/profile/user/styles.cljs
index a74b8a41dc..81e5024185 100644
--- a/src/status_im/ui/screens/profile/user/styles.cljs
+++ b/src/status_im/ui/screens/profile/user/styles.cljs
@@ -45,3 +45,27 @@
(defstyle my-profile-info-container
{:background-color colors/white})
+
+(def advanced-button
+ {:margin-top 16
+ :margin-bottom 12})
+
+(def advanced-button-container
+ {:align-items :center
+ :justify-content :center})
+
+(def advanced-button-container-background
+ {:padding-left 16
+ :padding-right 12
+ :padding-vertical 6
+ :border-radius 18
+ :background-color (colors/alpha colors/blue 0.1)})
+
+(def advanced-button-row
+ {:flex-direction :row
+ :align-items :center})
+
+(def advanced-button-label
+ {:font-size 15
+ :letter-spacing -0.2
+ :color colors/blue})
\ No newline at end of file
diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs
index f5820f69af..a2a0433f40 100644
--- a/src/status_im/ui/screens/profile/user/views.cljs
+++ b/src/status_im/ui/screens/profile/user/views.cljs
@@ -11,15 +11,16 @@
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
- [status-im.ui.components.styles :as components.styles]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.screens.profile.components.views :as profile.components]
[status-im.ui.screens.profile.components.styles :as profile.components.styles]
[status-im.ui.screens.profile.user.styles :as styles]
[status-im.utils.config :as config]
[status-im.utils.platform :as platform]
- [status-im.utils.utils :as utils]))
-
+ [status-im.utils.utils :as utils]
+ [status-im.ui.components.icons.vector-icons :as icons]
+ [status-im.ui.components.common.common :as components.common]
+ [clojure.string :as string]))
(defn my-profile-toolbar []
[toolbar/toolbar {}
@@ -87,22 +88,24 @@
:accessibility-label :share-my-contact-code-button}
[vector-icons/icon :icons/qr {:color colors/blue}]]]])
-(defn my-profile-settings [{:keys [network networks]}]
+(defn my-profile-settings [{:keys [seed-backed-up? mnemonic]}]
[react/view
[profile.components/settings-title (i18n/label :t/settings)]
- [profile.components/settings-item :t/main-currency "USD" #() false]
+ [profile.components/settings-item {:label-kw :t/main-currency
+ :value "USD"
+ :active? false}]
[profile.components/settings-item-separator]
- [profile.components/settings-item :t/notifications "" #(.openURL react/linking "app-settings://notification/status-im") true
+ [profile.components/settings-item {:label-kw :t/notifications
+ :action-fn #(.openURL react/linking "app-settings://notification/status-im")}
:notifications-button]
[profile.components/settings-item-separator]
- [profile.components/settings-item :t/network (get-in networks [network :name])
- #(re-frame/dispatch [:navigate-to :network-settings]) true :network-button]
- (when config/offline-inbox-enabled?
- [profile.components/settings-item-separator])
- (when config/offline-inbox-enabled?
- [profile.components/settings-item :t/offline-messaging-settings ""
- #(re-frame/dispatch [:navigate-to :offline-messaging-settings]) true
- :offline-messages-settings-button])])
+ (when (and (not seed-backed-up?) (not (string/blank? mnemonic)))
+ [react/view
+ [profile.components/settings-item
+ {:label-kw :t/backup-your-seed
+ :action-fn #(re-frame/dispatch [:navigate-to :backup-seed])
+ :icon-content [components.common/counter {:size 22} 1]}]
+ [profile.components/settings-item-separator]])])
(defn navigate-to-accounts []
;; TODO(rasom): probably not the best place for this call
@@ -124,6 +127,36 @@
:font (if platform/android? :medium :default)}
(i18n/label :t/logout)]]]])
+(defview advanced [{:keys [network networks dev-mode?]}]
+ (letsubs [advanced? [:get :my-profile/advanced?]]
+ [react/view
+ [react/touchable-highlight {:on-press #(re-frame/dispatch [:set :my-profile/advanced? (not advanced?)])
+ :style styles/advanced-button}
+ [react/view {:style styles/advanced-button-container}
+ [react/view {:style styles/advanced-button-container-background}
+ [react/view {:style styles/advanced-button-row}
+ [react/text {:style styles/advanced-button-label}
+ (i18n/label :t/wallet-advanced)]
+ [icons/icon (if advanced? :icons/up :icons/down) {:color colors/blue}]]]]]
+ (when advanced?
+ [react/view
+ [profile.components/settings-item
+ {:label-kw :t/network
+ :value (get-in networks [network :name])
+ :action-fn #(re-frame/dispatch [:navigate-to :network-settings])
+ :accessibility-label :network-button}]
+ (when config/offline-inbox-enabled?
+ [profile.components/settings-item-separator])
+ (when config/offline-inbox-enabled?
+ [profile.components/settings-item
+ {:label-kw :t/offline-messaging-settings
+ :action-fn #(re-frame/dispatch [:navigate-to :offline-messaging-settings])
+ :accessibility-label :offline-messages-settings-button}])
+ [profile.components/settings-item-separator]
+ [profile.components/settings-switch-item
+ {:label-kw :t/dev-mode
+ :value dev-mode?
+ :action-fn #(re-frame/dispatch [:switch-dev-mode %])}]])]))
(defview my-profile []
(letsubs [{:keys [public-key] :as current-account} [:get-current-account]
@@ -141,4 +174,5 @@
[share-contact-code current-account public-key]]
[react/view styles/my-profile-info-container
[my-profile-settings current-account]]
- [logout]]])))
+ [logout]
+ [advanced shown-account]]])))
\ No newline at end of file
diff --git a/src/status_im/ui/screens/subs.cljs b/src/status_im/ui/screens/subs.cljs
index 645d7a3765..47256a87e5 100644
--- a/src/status_im/ui/screens/subs.cljs
+++ b/src/status_im/ui/screens/subs.cljs
@@ -16,7 +16,8 @@
status-im.ui.screens.network-settings.subs
status-im.ui.screens.browser.subs
status-im.bots.subs
- status-im.ui.screens.add-new.new-chat.subs))
+ status-im.ui.screens.add-new.new-chat.subs
+ status-im.ui.screens.profile.subs))
(reg-sub :get
(fn [db [_ k]]
diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs
index 385dd8a291..e7194610d1 100644
--- a/src/status_im/ui/screens/views.cljs
+++ b/src/status_im/ui/screens/views.cljs
@@ -53,6 +53,7 @@
[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.ui.screens.profile.seed.views :refer [backup-seed]]
[status-im.utils.config :as config]))
;;; defines hierarchy of views, when parent screen is opened children screens
@@ -170,6 +171,7 @@
:recipient-qr-code recipient-qr-code
:contact-code contact-code
:profile-qr-viewer profile.user/qr-viewer
+ :backup-seed backup-seed
[react/view [react/text (str "Unknown view: " view-id)]])
main-screen-view (create-main-screen-view view-id)]
[main-screen-view common-styles/flex
diff --git a/src/status_im/ui/screens/wallet/subs.cljs b/src/status_im/ui/screens/wallet/subs.cljs
index 20722cee92..076bd110c3 100644
--- a/src/status_im/ui/screens/wallet/subs.cljs
+++ b/src/status_im/ui/screens/wallet/subs.cljs
@@ -44,3 +44,7 @@
(fn [wallet]
(or (get-in wallet [:errors :balance-update])
(get-in wallet [:errors :prices-update]))))
+
+(reg-sub :get-wallet-unread-messages-number
+ (fn [db]
+ 0))