feature #2906 - new profile screen

This commit is contained in:
Goran Jovic 2018-01-15 17:16:48 +01:00
parent 54e83c584d
commit ef57a5ca35
No known key found for this signature in database
GPG Key ID: A778DE3CD7D2D10D
6 changed files with 226 additions and 181 deletions

View File

@ -27,7 +27,9 @@
;;drawer
:switch-users "Switch users"
:logout "Logout"
:logout-title "Log out?"
:logout-are-you-sure "Are you sure you want\nto log out?"
:logout "Log out"
:current-network "Current network"
;;home
@ -83,10 +85,13 @@
;;profile
:profile "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"
@ -378,6 +383,7 @@
: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"

View File

@ -1,6 +1,9 @@
(ns status-im.ui.components.colors)
(def white "#ffffff")
(def white-light-transparent "rgba(255, 255, 255, 0.1)") ;; Used as icon background color on dark background
(def white-light-transparent "rgba(255, 255, 255, 0.1)") ;; Used as icon background color for a dark foreground
(def white-transparent "rgba(255, 255, 255, 0.2)") ;; Used as icon color on dark background
(def blue "#4360df") ;; Used as main wallet color
(def blue "#4360df") ;; Used as main wallet color
(def black "#000000") ;; Used as the default text color
(def gray "#939ba1") ;; Used as a background for a light foreground
(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions

View File

@ -1,4 +1,5 @@
(ns status-im.ui.components.styles)
(ns status-im.ui.components.styles
(:require [status-im.utils.platform :as platform]))
;; TODO(oskarth): Make a palette of all these colors
@ -157,3 +158,10 @@
(def main-container
{:background-color color-white
:flex 1})
;; TODO(goranjovic): replace all platform conditional uppercase styling with a reference to this var
(def uppercase?
(condp = platform/platform
"android" true
"ios" false
false))

View File

@ -1,32 +1,30 @@
(ns status-im.ui.screens.profile.styles
(:require [status-im.ui.components.styles
:as styles
:refer
[color-black
color-gray4
color-gray5
color-light-blue
color-light-gray
color-white
text1-color]]
(:require [status-im.ui.components.styles :as styles]
[status-im.ui.components.colors :as colors]
[status-im.utils.platform :as platform])
(:require-macros [status-im.utils.styles :refer [defstyle]]))
(defstyle toolbar-edit-text
{:padding-right 16
:color colors/blue
:ios {:font-size 15}
:android {:font-size 14}})
(def profile
{:flex 1
:background-color color-light-gray
:background-color colors/white
:flex-direction :column})
(def profile-form
{:background-color color-white
{:background-color colors/white
:padding 16})
(def edit-my-profile-form
{:background-color color-white
{:background-color colors/white
:flex 1})
(defstyle profile-info-container
{:background-color color-white})
{:background-color colors/white})
(def profile-info-item-button
{:padding 16})
@ -37,7 +35,7 @@
:padding-top 6})
(defstyle status-prompt-text
{:color color-gray4
{:color colors/gray
:ios {:font-size 14
:line-height 25
:letter-spacing -0.2}
@ -45,14 +43,16 @@
:font-size 12}})
(def profile-status-container
{:background-color color-light-gray
{:background-color colors/gray
:margin-top 16
:border-radius 4
:padding 16
:max-height 114})
(def profile-badge
{:flex-direction :row})
{:flex-direction :column
:justify-content :center
:align-items :center})
(def edit-profile-badge
{:flex-direction :row
@ -69,27 +69,27 @@
{:padding-top 25})
(def edit-name-title
{:color color-gray4
{:color colors/gray
:ios {:font-size 13
:letter-spacing -0.1}
:android {:font-size 12}})
(defstyle profile-name-text
{:ios {:font-size 17
:letter-spacing -0.2}
:android {:color color-black
:font-size 16}})
{:margin-top 8
:font-size 15
:text-align :center
:ios {:letter-spacing -0.2}
:android {:color colors/black}})
(def profile-badge-name-container
{:flex 1
:justify-content :center
:padding-left 16})
:justify-content :center})
(def profile-activity-status-container
{:margin-top 4})
(defstyle profile-activity-status-text
{:color color-gray4
{:color colors/gray
:ios {:font-size 14
:line-height 20
:letter-spacing -0.2}
@ -107,24 +107,19 @@
{:flex 1
:padding-right (if options 16 40)})
(defstyle profile-setting-title
{:color color-gray4
:ios {:font-size 14
:letter-spacing -0.2}
:android {:font-size 12}})
(defstyle profile-settings-title
{:color colors/gray
:margin-left 16
:margin-top 18
:margin-bottom 20
:font-size 14
:ios {:letter-spacing -0.2}})
(defstyle profile-setting-text
{:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 16
:color color-black}})
(defstyle logout-text
{:padding-left 16
:color styles/color-red
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 16}})
:color colors/black}})
(defstyle profile-setting-spacing
{:ios {:height 10}
@ -132,45 +127,48 @@
(def profile-setting-text-empty
(merge profile-setting-text
{:color color-gray4}))
{:color colors/gray}))
(def info-item-separator
(def settings-item-separator
{:margin-left 16})
(defstyle network-settings
(defstyle settings-item
{:padding-horizontal 16
:flex-direction :row
:align-items :center
:background-color color-white
:android {:height 72}
:ios {:height 64}})
:background-color colors/white
:height 52})
(defstyle offline-messaging-settings
{:padding-horizontal 16
:flex-direction :row
:align-items :center
:background-color color-white
:background-color colors/white
:android {:height 72}
:ios {:height 64}})
(def network-settings-text
(merge {:flex 1}
profile-setting-text))
(defstyle settings-item-text
{:flex 1
:font-size 15
:ios {:letter-spacing -0.2}
:android {:color colors/black}})
(def offline-messaging-settings-text
(merge {:flex 1}
profile-setting-text))
(def settings-item-value
{:padding-right 10
:font-size 15
:color colors/gray})
(defstyle logout-text
(merge settings-item-text
{:color colors/red}))
(def edit-line-color
(if platform/ios?
(str color-gray5 "80")
color-gray5))
(def profile-focus-line-color
color-light-blue)
(str styles/color-gray5 "80")
styles/color-gray5))
(defstyle profile-name-input
{:color text1-color
{:color styles/text1-color
:ios {:font-size 17
:padding-bottom 0
:line-height 17
@ -183,7 +181,7 @@
(defstyle profile-status-input
{:line-height 24 ;;TODO doesnt' work for multiline because a bug in the RN
:color text1-color
:color colors/black
:padding-left 0
:ios {:font-size 17
:padding-bottom 0
@ -197,14 +195,14 @@
:padding-bottom 0}})
(defstyle profile-status-text
{:color text1-color
{:color colors/black
:line-height 24
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 16}})
(defstyle edit-profile-status
{:background-color color-light-gray
{:background-color styles/color-light-gray
:border-radius 4
:height 90
:padding-horizontal 16
@ -218,6 +216,34 @@
(def add-a-status
(merge profile-status-text
{:color color-gray4}))
{:color colors/gray}))
(def network-info {:background-color :white})
(def share-contact-code
{:margin-horizontal 16
:flex-direction :row
:justify-content :space-between
:align-items :center
:height 42
:border-radius 8
:background-color styles/color-blue4-transparent})
(def share-contact-code-text-container
{:padding-left 16
:padding-bottom 1
:flex 0.9
:flex-direction :row
:justify-content :center
:align-items :center})
(def share-contact-code-text
{:color colors/blue
:font-size 15})
(def share-contact-icon-container
{:border-radius 50
:flex 0.1
:padding-right 5
:align-items :center
:justify-content :center})

View File

@ -1,24 +1,24 @@
(ns status-im.ui.screens.profile.views
(:require [clojure.string :as string]
[re-frame.core :refer [dispatch]]
[status-im.ui.components.action-button.action-button
:refer
[action-button action-button-disabled action-separator]]
[status-im.ui.components.action-button.styles :refer [actions-list]]
[status-im.ui.components.chat-icon.screen :refer [my-profile-icon]]
[re-frame.core :as re-frame]
[status-im.ui.components.action-button.action-button :as action-button]
[status-im.ui.components.action-button.styles :as action-button.styles]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.common.common :as common]
[status-im.ui.components.context-menu :refer [context-menu]]
[status-im.ui.components.list-selection :refer [share-options]]
[status-im.ui.components.context-menu :as context-menu]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.status-bar.view :refer [status-bar]]
[status-im.ui.components.styles :refer [color-blue]]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.styles :as component.styles]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.toolbar.actions :as actions]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.i18n :refer [label]]
[status-im.i18n :as i18n]
[status-im.ui.screens.profile.styles :as styles]
[status-im.ui.components.colors :as colors]
[status-im.utils.utils :as utils]
[status-im.utils.datetime :as time]
[status-im.utils.utils :refer [hash-tag?]]
[status-im.utils.config :as config]
[status-im.utils.platform :as platform]
[status-im.protocol.core :as protocol]
@ -29,9 +29,11 @@
[toolbar/toolbar {}
nil
[toolbar/content-title ""]
[toolbar/actions
[(actions/opts [{:value #(dispatch [:my-profile/edit-profile])
:text (label :t/edit)}])]]])
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:my-profile/edit-profile])}
[react/view
[react/text {:style styles/toolbar-edit-text
:uppercase? component.styles/uppercase?} (i18n/label :t/edit)]]]])
(defn profile-toolbar [contact]
[toolbar/toolbar {}
@ -40,8 +42,8 @@
[toolbar/actions
(when (and (not (:pending? contact))
(not (:unremovable? contact)))
[(actions/opts [{:value #(dispatch [:hide-contact contact])
:text (label :t/remove-from-contacts)}])])]])
[(actions/opts [{:value #(re-frame/dispatch [:hide-contact contact])
:text (i18n/label :t/remove-from-contacts)}])])]])
(defn online-text [last-online]
(let [last-online-date (time/to-date last-online)
@ -49,12 +51,12 @@
(if (and (pos? last-online)
(<= last-online-date now-date))
(time/time-ago last-online-date)
(label :t/active-unknown))))
(i18n/label :t/active-unknown))))
(defn profile-badge [{:keys [name last-online] :as contact}]
[react/view styles/profile-badge
[my-profile-icon {:account contact
:edit? false}]
[chat-icon.screen/my-profile-icon {:account contact
:edit? false}]
[react/view styles/profile-badge-name-container
[react/text {:style styles/profile-name-text
:number-of-lines 1}
@ -65,30 +67,30 @@
(online-text last-online)]])]])
(defn profile-actions [{:keys [pending? whisper-identity dapp?]} chat-id]
[react/view actions-list
[react/view action-button.styles/actions-list
(if pending?
[action-button {:label (label :t/add-to-contacts)
:icon :icons/add
:icon-opts {:color :blue}
:on-press #(dispatch [:add-pending-contact chat-id])}]
[action-button-disabled {:label (label :t/in-contacts) :icon :icons/ok}])
[action-separator]
[action-button {:label (label :t/start-conversation)
:icon :icons/chats
:icon-opts {:color :blue}
:on-press #(dispatch [:profile/send-message whisper-identity])}]
[action-button/action-button {:label (i18n/label :t/add-to-contacts)
:icon :icons/add
:icon-opts {:color :blue}
:on-press #(re-frame/dispatch [:add-pending-contact chat-id])}]
[action-button/action-button-disabled {:label (i18n/label :t/in-contacts) :icon :icons/ok}])
[action-button/action-separator]
[action-button/action-button {:label (i18n/label :t/start-conversation)
:icon :icons/chats
:icon-opts {:color :blue}
:on-press #(re-frame/dispatch [:profile/send-message whisper-identity])}]
(when-not dapp?
[react/view
[action-separator]
[action-button {:label (label :t/send-transaction)
:icon :icons/arrow-right
:icon-opts {:color :blue}
:on-press #(dispatch [:profile/send-transaction chat-id whisper-identity])}]])])
[action-button/action-separator]
[action-button/action-button {:label (i18n/label :t/send-transaction)
:icon :icons/arrow-right
:icon-opts {:color :blue}
:on-press #(re-frame/dispatch [:profile/send-transaction chat-id whisper-identity])}]])])
(defn profile-info-item [{:keys [label value options text-mode empty-value? accessibility-label]}]
[react/view styles/profile-setting-item
[react/view (styles/profile-info-text-container options)
[react/text {:style styles/profile-setting-title}
[react/text {:style styles/profile-settings-title}
label]
[react/view styles/profile-setting-spacing]
[react/text {:style (if empty-value?
@ -99,27 +101,27 @@
:accessibility-label accessibility-label}
value]]
(when options
[context-menu
[context-menu/context-menu
[vector-icons/icon :icons/options]
options
nil
styles/profile-info-item-button])])
(defn show-qr [contact qr-source qr-value]
#(dispatch [:navigate-to-modal :qr-code-view {:contact contact
:qr-source qr-source
:qr-value qr-value}]))
#(re-frame/dispatch [:navigate-to-modal :qr-code-view {:contact contact
:qr-source qr-source
:qr-value qr-value}]))
(defn profile-options [contact k text]
(into []
(concat [{:value (show-qr contact k text)
:text (label :t/show-qr)}]
:text (i18n/label :t/show-qr)}]
(when text
(share-options text)))))
(list-selection/share-options text)))))
(defn profile-info-address-item [{:keys [address] :as contact}]
[profile-info-item
{:label (label :t/address)
{:label (i18n/label :t/address)
:value address
:options (profile-options contact :address address)
:text-mode :middle
@ -127,23 +129,23 @@
(defn profile-info-public-key-item [public-key contact]
[profile-info-item
{:label (label :t/public-key)
{:label (i18n/label :t/public-key)
:value public-key
:options (profile-options contact :public-key public-key)
:text-mode :middle
:accessibility-label :profile-public-key}])
(defn info-item-separator []
[common/separator styles/info-item-separator])
(defn settings-item-separator []
[common/separator styles/settings-item-separator])
(defn tag-view [tag]
[react/text {:style {:color color-blue}
[react/text {:style {:color colors/blue}
:font :medium}
(str tag " ")])
(defn colorize-status-hashtags [status]
(for [[i status] (map-indexed vector (string/split status #" "))]
(if (hash-tag? status)
(if (utils/hash-tag? status)
^{:key (str "item-" i)}
[tag-view status]
^{:key (str "item-" i)}
@ -151,85 +153,82 @@
(defn profile-info-phone-item [phone & [options]]
(let [phone-empty? (or (nil? phone) (string/blank? phone))
phone-text (if phone-empty?
(label :t/not-specified)
phone)]
[profile-info-item {:label (label :t/phone-number)
phone-text (if phone-empty?
(i18n/label :t/not-specified)
phone)]
[profile-info-item {:label (i18n/label :t/phone-number)
:value phone-text
:options options
:empty-value? phone-empty?
:accessibility-label :profile-phone-number}]))
(defn network-settings []
[react/touchable-highlight
{:on-press #(dispatch [:navigate-to :network-settings])}
[react/view styles/network-settings
[react/text {:style styles/network-settings-text}
(label :t/network-settings)]
[vector-icons/icon :icons/forward {:color :gray}]]])
(defn settings-title [title]
[react/text {:style styles/profile-settings-title}
title])
(defn offline-messaging-settings []
(defn settings-item [label-kw value action-fn active?]
[react/touchable-highlight
{:on-press #(dispatch [:navigate-to :offline-messaging-settings])}
[react/view styles/offline-messaging-settings
[react/text {:style styles/offline-messaging-settings-text}
(label :t/offline-messaging-settings)]
[vector-icons/icon :icons/forward {:color :gray}]]])
{:on-press action-fn
:disabled (not active?)}
[react/view styles/settings-item
[react/text {:style styles/settings-item-text}
(i18n/label label-kw)]
[react/text {:style styles/settings-item-value
:uppercase? component.styles/uppercase?} value]
(when active?
[vector-icons/icon :icons/forward {:color colors/gray}])]])
(defn profile-info [{:keys [whisper-identity status phone] :as contact}]
(defn profile-info [{:keys [whisper-identity phone] :as contact}]
[react/view
[profile-info-address-item contact]
[info-item-separator]
[settings-item-separator]
[profile-info-public-key-item whisper-identity contact]
[info-item-separator]
[settings-item-separator]
[profile-info-phone-item phone]])
(defn save-profile! []
(when-let [save-event @(re-frame/subscribe [:my-profile.drawer/save-event])]
(re-frame/dispatch [save-event])))
(defn navigate-to-accounts []
(save-profile!)
;; TODO(rasom): probably not the best place for this call
(protocol/stop-whisper!)
(re-frame/dispatch [:navigate-to :accounts]))
(defn handle-logout []
(utils/show-confirmation (i18n/label :t/logout-title)
(i18n/label :t/logout-are-you-sure)
(i18n/label :t/logout) navigate-to-accounts))
(defn logout []
[react/view {}
[react/touchable-highlight
{:on-press navigate-to-accounts}
[react/view
[react/text {:style styles/logout-text
:font (if platform/android? :medium :default)}
(label :t/logout)]]]])
{:on-press handle-logout}
[react/view styles/settings-item
[react/text {:style styles/logout-text
:font (if platform/android? :medium :default)}
(i18n/label :t/logout)]]]])
(defn my-profile-info [{:keys [public-key status phone] :as contact}]
(defn my-profile-settings [{:keys [network networks]}]
[react/view
[profile-info-address-item contact]
[info-item-separator]
[profile-info-public-key-item public-key contact]
[info-item-separator]
[profile-info-phone-item
phone
[{:value #(dispatch [:my-profile/update-phone-number])
:text (label :t/edit)}]]
[info-item-separator]
[network-settings]
[settings-title (i18n/label :t/settings)]
[settings-item :t/main-currency "USD" #() false]
[settings-item-separator]
[settings-item :t/notifications "" #() true]
[settings-item-separator]
[settings-item :t/network (get-in networks [network :name])
#(re-frame/dispatch [:navigate-to :network-settings]) true]
(when config/offline-inbox-enabled?
[info-item-separator])
[settings-item-separator])
(when config/offline-inbox-enabled?
[offline-messaging-settings])
[logout]])
[settings-item :t/offline-messaging-settings ""
#(re-frame/dispatch [:navigate-to :offline-messaging-settings]) true])])
(defn profile-status [status & [edit?]]
[react/view styles/profile-status-container
(if (or (nil? status) (string/blank? status))
[react/touchable-highlight {:on-press #(dispatch [:my-profile/edit-profile :edit-status])}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:my-profile/edit-profile :edit-status])}
[react/view
[react/text {:style styles/add-a-status}
(label :t/add-a-status)]]]
(i18n/label :t/add-a-status)]]]
[react/scroll-view
[react/touchable-highlight {:on-press (when edit? #(dispatch [:my-profile/edit-profile :edit-status]))}
[react/touchable-highlight {:on-press (when edit? #(re-frame/dispatch [:my-profile/edit-profile :edit-status]))}
[react/view
[react/text {:style styles/profile-status-text}
(colorize-status-hashtags status)]]]])])
@ -239,34 +238,35 @@
[common/network-info]
[common/separator]])
(defn share-contact-code [current-account public-key]
[react/touchable-highlight {:on-press (show-qr current-account :public-key public-key)}
[react/view styles/share-contact-code
[react/view styles/share-contact-code-text-container
[react/text {:style styles/share-contact-code-text
:uppercase? component.styles/uppercase?}
(i18n/label :t/share-contact-code)]]
[react/view styles/share-contact-icon-container
[vector-icons/icon :icons/qr {:color colors/blue}]]]])
(defview my-profile []
(letsubs [{:keys [status public-key] :as current-account} [:get-current-account]]
(letsubs [{:keys [public-key] :as current-account} [:get-current-account]]
[react/view styles/profile
[my-profile-toolbar]
[network-info]
[react/scroll-view
[react/view styles/profile-form
[profile-badge current-account]
[profile-status status true]]
[common/form-spacer]
[react/view actions-list
[action-button {:label (label :t/show-qr)
:icon :icons/qr
:icon-opts {:color :blue}
:on-press (show-qr current-account :public-key public-key)}]]
[common/form-spacer]
[profile-badge current-account]]
[react/view action-button.styles/actions-list
[share-contact-code current-account public-key]]
[react/view styles/profile-info-container
[my-profile-info current-account]
[common/bottom-shadow]]]]))
[my-profile-settings current-account]]
[logout]]]))
(defview profile []
(letsubs [{:keys [pending?
status
whisper-identity]
(letsubs [{:keys [status]
:as contact} [:contact]
chat-id [:get :current-chat-id]]
chat-id [:get :current-chat-id]]
[react/view styles/profile
[status-bar]
[status-bar/status-bar]
[profile-toolbar contact]
[network-info]
[react/scroll-view

View File

@ -1,5 +1,4 @@
(ns status-im.utils.ethereum.tokens
(:require [status-im.ui.components.styles :as styles])
(:require-macros [status-im.utils.ethereum.macros :refer [resolve-icons]]))
(defn- asset-border [color]
@ -9,7 +8,10 @@
:symbol :ETH
:decimals 18
:icon {:source (js/require "./resources/images/assets/ethereum.png")
:style (asset-border styles/color-light-blue-transparent)}})
;; TODO(goranjovic) find a better place to set UI info
;; like colors. Removed the reference to component.styles to
;; avoid circular dependency between namespaces.
:style (asset-border "#628fe333")}})
(defn ethereum? [k]
(= k (:symbol ethereum)))