Merge pull request #320 from status-im/feature/#294

Status & Name, quick profile change in drawer (#294), length limit (#324)

Former-commit-id: 2cbad4dc76
This commit is contained in:
Roman Volosovskyi 2016-10-05 14:18:12 +03:00 committed by GitHub
commit 6530f9c4e4
6 changed files with 190 additions and 119 deletions

View File

@ -9,7 +9,8 @@
separator-color separator-color
text1-color text1-color
text2-color text2-color
text3-color]])) text3-color
color-red]]))
(def drawer-menu (def drawer-menu
{:flex 1 {:flex 1
@ -27,14 +28,38 @@
:height 64}) :height 64})
(def name-container (def name-container
{:margin-top 20 {:margin-top -16
:margin-bottom -16
:margin-left 16 :margin-left 16
:margin-right 16})
(def name-input-wrapper
{})
(defn name-input-text [valid?]
{:color (if valid? text1-color
color-red)
:text-align :center})
(def status-container
{:margin-left 16
:margin-right 16 :margin-right 16
:margin-top 4
:align-items :center}) :align-items :center})
(def status-input
{:align-self "stretch"
:height 56
:font-size 14
:padding-left 4
:line-height 20
:text-align :center
:text-align-vertical :top
:color text2-color})
(def menu-items-container (def menu-items-container
{:flex 1 {:flex 1
:margin-top 50 :margin-top 20
:align-items :stretch :align-items :stretch
:flex-direction :column}) :flex-direction :column})

View File

@ -1,17 +1,23 @@
(ns status-im.components.drawer.view (ns status-im.components.drawer.view
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview]])
(:require [clojure.string :as s] (:require [reagent.core :as r]
[re-frame.core :refer [subscribe dispatch dispatch-sync]] [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[reagent.core :as r] [clojure.string :as str]
[status-im.components.react :refer [react-native [cljs.spec :as s]
view [status-im.components.react :refer [view
text text
text-input
image image
drawer-layout drawer-layout
touchable-without-feedback
touchable-opacity]] touchable-opacity]]
[status-im.resources :as res] [status-im.components.text-field.view :refer [text-field]]
[status-im.components.drawer.styles :as st] [status-im.components.drawer.styles :as st]
[status-im.i18n :refer [label]])) [status-im.profile.validations :as v]
[status-im.profile.handlers :refer [update-profile]]
[status-im.resources :as res]
[status-im.i18n :refer [label]]
[status-im.components.react :refer [dismiss-keyboard!]]))
(defonce drawer-atom (atom)) (defonce drawer-atom (atom))
@ -22,7 +28,7 @@
(.closeDrawer @drawer-atom)) (.closeDrawer @drawer-atom))
(defn user-photo [{:keys [photo-path]}] (defn user-photo [{:keys [photo-path]}]
[image {:source (if (s/blank? photo-path) [image {:source (if (str/blank? photo-path)
res/user-no-photo res/user-no-photo
{:uri photo-path}) {:uri photo-path})
:style st/user-photo}]) :style st/user-photo}])
@ -37,47 +43,70 @@
name]]) name]])
(defview drawer-menu [] (defview drawer-menu []
[{:keys [name address photo-path]} [:get-current-account]] [{:keys [name address photo-path status] :as account} [:get-current-account]
{new-name :name :as profile-edit-data} [:get :profile-edit]
keyboard-height [:get :keyboard-height]]
[view st/drawer-menu [view st/drawer-menu
[view st/user-photo-container [touchable-without-feedback {:on-press #(dismiss-keyboard!)}
[user-photo {:photo-path photo-path}]] [view st/drawer-menu
[view st/name-container [touchable-opacity {:on-press #(dispatch [:navigate-to :my-profile])}
[text {:style st/name-text [view st/user-photo-container
:number-of-lines 1 [user-photo {:photo-path photo-path}]]]
:font :default} [view st/name-container
(if (= name address) [text-field
(label :t/user-anonymous) {:line-color :white
name)]] :focus-line-color :white
[view st/menu-items-container :placeholder (label :t/user-anonymous)
[menu-item {:name (label :t/profile) :editable true
:handler #(dispatch [:navigate-to :my-profile])}] :input-style (st/name-input-text (s/valid? ::v/name (or new-name name)))
[menu-item {:name (label :t/settings) :wrapper-style st/name-input-wrapper
:handler (fn [] :value (if (not= name address)
;; TODO not implemented name)
)}] :on-change-text #(dispatch [:set-in [:profile-edit :name] %])
[menu-item {:name (label :t/discovery) :on-end-editing #(update-profile account profile-edit-data)}]]
:handler #(dispatch [:navigate-to :discovery])}] [view st/status-container
[menu-item {:name (label :t/contacts) [text-input {:style st/status-input
:handler #(dispatch [:navigate-to :contact-list])}] :editable true
[menu-item {:name (label :t/invite-friends) :multiline true
:handler (fn [] :blur-on-submit true
;; TODO not implemented :maxLength 140
)}] :accessibility-label :input
[menu-item {:name (label :t/faq) :placeholder (label :t/profile-no-status)
:handler (fn [])}]] :on-change-text #(dispatch [:set-in [:profile-edit :status] %])
[view st/switch-users-container :on-blur #(update-profile account profile-edit-data)
[touchable-opacity {:onPress (fn [] :default-value status}]]
(close-drawer) [view st/menu-items-container
(dispatch [:navigate-to :accounts]) [menu-item {:name (label :t/profile)
;; TODO not implemented :handler #(dispatch [:navigate-to :my-profile])}]
)} [menu-item {:name (label :t/settings)
[text {:style st/switch-users-text :handler (fn []
:font :default} ;; TODO not implemented
(label :t/switch-users)]]]]) )}]
[menu-item {:name (label :t/discovery)
:handler #(dispatch [:navigate-to :discovery])}]
[menu-item {:name (label :t/contacts)
:handler #(dispatch [:navigate-to :contact-list])}]
[menu-item {:name (label :t/invite-friends)
:handler (fn []
;; TODO not implemented
)}]
[menu-item {:name (label :t/faq)
:handler (fn [])}]]
(when (= keyboard-height 0)
[view st/switch-users-container
[touchable-opacity {:onPress (fn []
(close-drawer)
(dispatch [:navigate-to :accounts])
;; TODO not implemented
)}
[text {:style st/switch-users-text
:font :default}
(label :t/switch-users)]]])]]])
(defn drawer-view [items] (defn drawer-view [items]
[drawer-layout {:drawerWidth 260 [drawer-layout {:drawerWidth 260
:render-navigation-view #(r/as-element [drawer-menu]) :renderNavigationView #(r/as-element [drawer-menu])
:ref (fn [drawer] :onDrawerSlide dismiss-keyboard!
(reset! drawer-atom drawer))} :ref (fn [drawer]
(reset! drawer-atom drawer))}
items]) items])

View File

@ -8,11 +8,10 @@
(def color-gray "#838c93de") (def color-gray "#838c93de")
(def color-gray2 "#8f838c93") (def color-gray2 "#8f838c93")
(def color-gray3 "#00000040") (def color-gray3 "#00000040")
(def color-white :white) (def color-white "white")
(def color-light-blue "#bbc4cb")
(def color-light-blue-transparent "#bbc4cb32") (def color-light-blue-transparent "#bbc4cb32")
(def color-dark-mint "#5fc48d")
(def color-light-gray "#EEF2F5") (def color-light-gray "#EEF2F5")
(def color-red "red")
(def text1-color color-black) (def text1-color color-black)
(def text1-disabled-color "#555555") (def text1-disabled-color "#555555")

View File

@ -144,10 +144,10 @@
label-font-size label-font-size
line-width line-width
current-value current-value
max-line-width] :as state} (r/state component) max-line-width]} (r/state component)
{:keys [wrapper-style input-style label-hidden? line-color focus-line-color secure-text-entry {:keys [wrapper-style input-style label-hidden? line-color focus-line-color secure-text-entry
label-color error-color error label value on-focus on-blur label-color error-color error label value on-focus on-blur
on-change-text on-change editable] :as props} (merge default-props (r/props component)) on-change-text on-change on-end-editing editable placeholder]} (merge default-props (r/props component))
line-color (if error error-color line-color) line-color (if error error-color line-color)
focus-line-color (if error error-color focus-line-color) focus-line-color (if error error-color focus-line-color)
label-color (if (and error (not float-label?)) error-color label-color) label-color (if (and error (not float-label?)) error-color label-color)
@ -157,7 +157,7 @@
(when-not label-hidden? (when-not label-hidden?
[animated-text {:style (st/label label-top label-font-size label-color)} label]) [animated-text {:style (st/label label-top label-font-size label-color)} label])
[text-input {:style (merge st/text-input input-style) [text-input {:style (merge st/text-input input-style)
:placeholder "" :placeholder (or placeholder "")
:editable editable :editable editable
:secure-text-entry secure-text-entry :secure-text-entry secure-text-entry
:on-focus #(on-input-focus {:component component :on-focus #(on-input-focus {:component component
@ -181,7 +181,9 @@
(r/set-state component {:current-value text}) (r/set-state component {:current-value text})
(on-change-text text)) (on-change-text text))
:on-change #(on-change %) :on-change #(on-change %)
:default-value value}] :default-value value
:on-end-editing (when on-end-editing
on-end-editing)}]
[view {:style (st/underline-container line-color) [view {:style (st/underline-container line-color)
:onLayout #(r/set-state component {:max-line-width (get-width %)})} :onLayout #(r/set-state component {:max-line-width (get-width %)})}
[animated-view {:style (st/underline focus-line-color line-width)}]] [animated-view {:style (st/underline focus-line-color line-width)}]]

View File

@ -6,7 +6,9 @@
[status-im.i18n :refer [label]] [status-im.i18n :refer [label]]
[status-im.utils.handlers :as u :refer [get-hashtags]] [status-im.utils.handlers :as u :refer [get-hashtags]]
[status-im.utils.platform :refer [ios?]] [status-im.utils.platform :refer [ios?]]
[clojure.string :as str])) [clojure.string :as str]
[status-im.profile.validations :as v]
[cljs.spec :as s]))
(defn message-user [identity] (defn message-user [identity]
(when identity (when identity
@ -20,7 +22,11 @@
new-email :email new-email :email
new-status :status new-status :status
new-photo-path :photo-path}] new-photo-path :photo-path}]
(let [new-name (if (or (not new-name) (str/blank? new-name)) name new-name) (let [new-name (if (or (not new-name)
(str/blank? new-name)
(not (s/valid? ::v/name new-name)))
name
new-name)
status-updated? (and (not= new-status nil) status-updated? (and (not= new-status nil)
(not= status new-status))] (not= status new-status))]
(when status-updated? (when status-updated?

View File

@ -3,6 +3,7 @@
(:require [re-frame.core :refer [subscribe dispatch]] (:require [re-frame.core :refer [subscribe dispatch]]
[clojure.string :as str] [clojure.string :as str]
[cljs.spec :as s] [cljs.spec :as s]
[reagent.core :as r]
[status-im.components.react :refer [view [status-im.components.react :refer [view
text text
text-input text-input
@ -32,11 +33,7 @@
[view [view
[touchable-highlight {:style st/back-btn-touchable [touchable-highlight {:style st/back-btn-touchable
:on-press (fn [] :on-press (fn []
(dispatch [:set :profile-edit {:edit? false (dispatch [:set-in [:profile-edit :edit?] false])
:name nil
:email nil
:status nil
:photo-path nil}])
(dispatch [:navigate-back]))} (dispatch [:navigate-back]))}
[view st/back-btn-container [view st/back-btn-container
[icon :back st/back-btn-icon]]] [icon :back st/back-btn-icon]]]
@ -77,10 +74,11 @@
(label :t/user-anonymous) (label :t/user-anonymous)
username)] username)]
[text-input {:style st/status-input [text-input {:style st/status-input
:maxLength 140
:editable edit? :editable edit?
:placeholder (label :t/profile-no-status) :placeholder (label :t/profile-no-status)
:on-change-text #(dispatch [:set-in [:profile-edit :status] %]) :on-change-text #(dispatch [:set-in [:profile-edit :status] %])
:value status}]]) :default-value status}]])
(defview profile [] (defview profile []
[{whisper-identity :whisper-identity [{whisper-identity :whisper-identity
@ -156,70 +154,82 @@
)} )}
[view [text {:style st/report-user-text} (label :t/report-user)]]]]]]) [view [text {:style st/report-user-text} (label :t/report-user)]]]]]])
(defview my-profile [] (defview my-profile-render []
[{public-key :public-key [{public-key :public-key
address :address address :address
username :name username :name
email :email email :email
photo-path :photo-path photo-path :photo-path
phone :phone phone :phone
status :status status :status
:as account} [:get-current-account] :as account} [:get-current-account]
{edit? :edit? {edit? :edit?
new-name :name new-name :name
new-email :email new-email :email
new-status :status new-status :status
new-photo-path :photo-path new-photo-path :photo-path
:as profile-edit-data} [:get :profile-edit]] :as profile-edit-data} [:get :profile-edit]]
[scroll-view {:style st/profile} [scroll-view {:style st/profile}
[status-bar] [status-bar]
[toolbar {:account account [toolbar {:account account
:profile-edit-data profile-edit-data :profile-edit-data profile-edit-data
:edit? edit?}] :edit? edit?}]
[status-image-view {:account account [status-image-view {:account account
:photo-path (or new-photo-path photo-path) :photo-path (or new-photo-path photo-path)
:status (or new-status status) :status (or new-status status)
:edit? edit?}] :edit? edit?}]
[scroll-view st/profile-properties-container [scroll-view st/profile-properties-container
[text-field [text-field
{:error (if-not (s/valid? ::v/name new-name) {:error (if-not (s/valid? ::v/name new-name)
(label :t/error-incorrect-name)) (label :t/error-incorrect-name))
:error-color "#7099e6" :error-color "#7099e6"
:editable edit? :editable edit?
:input-style (if edit? :input-style (if edit?
st/profile-input-text st/profile-input-text
st/profile-input-text-non-editable) st/profile-input-text-non-editable)
:wrapper-style st/profile-input-wrapper :wrapper-style st/profile-input-wrapper
:value (if (not= username address) :value (if (not= username address)
username) username)
:label (label :t/username) :label (label :t/username)
:on-change-text #(dispatch [:set-in [:profile-edit :name] %])}] :on-change-text #(dispatch [:set-in [:profile-edit :name] %])}]
[text-field [text-field
{:editable false {:editable false
:input-style st/profile-input-text-non-editable :input-style st/profile-input-text-non-editable
:wrapper-style st/profile-input-wrapper :wrapper-style st/profile-input-wrapper
:value (if (and phone (not (str/blank? phone))) :value (if (and phone (not (str/blank? phone)))
(format-phone-number phone)) (format-phone-number phone))
:label (label :t/phone-number)}] :label (label :t/phone-number)}]
[text-field [text-field
{:error (if-not (s/valid? ::v/email new-email) {:error (if-not (s/valid? ::v/email new-email)
(label :t/error-incorrect-email)) (label :t/error-incorrect-email))
:error-color "#7099e6" :error-color "#7099e6"
:editable edit? :editable edit?
:input-style (if edit? :input-style (if edit?
st/profile-input-text st/profile-input-text
st/profile-input-text-non-editable) st/profile-input-text-non-editable)
:wrapper-style st/profile-input-wrapper :wrapper-style st/profile-input-wrapper
:value (if (and email (not (str/blank? email))) :value (if (and email (not (str/blank? email)))
email) email)
:label (label :t/email) :label (label :t/email)
:on-change-text #(dispatch [:set-in [:profile-edit :email] %])}] :on-change-text #(dispatch [:set-in [:profile-edit :email] %])}]
[view st/qr-code-container [view st/qr-code-container
;; TODO: this public key should be replaced by address ;; TODO: this public key should be replaced by address
[qr-code {:value (str "ethereum:" public-key) [qr-code {:value (str "ethereum:" public-key)
:size 220}]]]]) :size 220}]]]])
(defview my-profile []
[{username :name
email :email} [:get-current-account]]
(r/create-class
{:component-will-mount
(fn []
(dispatch [:set :profile-edit {:edit? false
:name username
:email email}]))
:reagent-render
my-profile-render}))