From 5ecdb174e2437cb52b50a6ca34922e86b67751bb Mon Sep 17 00:00:00 2001 From: Goran Jovic Date: Mon, 15 Jan 2018 17:16:48 +0100 Subject: [PATCH] feature #3052 and #3054 - edit profile and qr code viewer --- src/status_im/commands/utils.cljs | 4 +- src/status_im/translations/en.cljs | 3 +- .../ui/components/chat_icon/screen.cljs | 199 +++++++++--------- src/status_im/ui/components/colors.cljs | 3 +- .../ui/components/common/common.cljs | 15 +- .../ui/components/common/styles.cljs | 18 +- src/status_im/ui/components/context_menu.cljs | 11 +- src/status_im/ui/components/qr_code.cljs | 8 - .../ui/components/qr_code_viewer/styles.cljs | 97 +++++++++ .../ui/components/qr_code_viewer/views.cljs | 59 ++++++ src/status_im/ui/screens/db.cljs | 4 +- .../ui/screens/profile/edit/views.cljs | 104 --------- src/status_im/ui/screens/profile/events.cljs | 19 +- .../ui/screens/profile/navigation.cljs | 5 +- .../ui/screens/profile/qr_code/styles.cljs | 103 --------- .../ui/screens/profile/qr_code/views.cljs | 51 ----- src/status_im/ui/screens/profile/styles.cljs | 35 +-- src/status_im/ui/screens/profile/views.cljs | 72 ++++++- src/status_im/ui/screens/views.cljs | 10 +- .../ui/screens/wallet/request/views.cljs | 4 +- 20 files changed, 398 insertions(+), 426 deletions(-) delete mode 100644 src/status_im/ui/components/qr_code.cljs create mode 100644 src/status_im/ui/components/qr_code_viewer/styles.cljs create mode 100644 src/status_im/ui/components/qr_code_viewer/views.cljs delete mode 100644 src/status_im/ui/screens/profile/edit/views.cljs delete mode 100644 src/status_im/ui/screens/profile/qr_code/styles.cljs delete mode 100644 src/status_im/ui/screens/profile/qr_code/views.cljs diff --git a/src/status_im/commands/utils.cljs b/src/status_im/commands/utils.cljs index effb23d087..909af0486f 100644 --- a/src/status_im/commands/utils.cljs +++ b/src/status_im/commands/utils.cljs @@ -6,7 +6,7 @@ [status-im.chat.views.input.web-view :as chat-web-view] [status-im.chat.views.input.validation-messages :as chat-validation-messages] [status-im.chat.views.api.choose-contact :as choose-contact] - [status-im.ui.components.qr-code :as qr] + [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.components.chat-preview :as chat-preview] [status-im.chat.views.api.geolocation.views :as geolocation] [status-im.utils.handlers :refer [register-handler]] @@ -25,7 +25,7 @@ :text-input components/text-input :chat-preview-text chat-preview/text :image components/image - :qr-code qr/qr-code + :qr-code qr-code-viewer/qr-code :linking components/linking :slider components/slider :scroll-view components/scroll-view diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 00fea83580..adc1bca0db 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -103,7 +103,7 @@ :mainnet-text "You’re on the Mainnet. Real ETH will be sent" ;;make_photo - :image-source-title "Profile image" + :image-source-title "Edit picture" :image-source-make-photo "Capture" :image-source-gallery "Select from gallery" @@ -183,6 +183,7 @@ :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" :more "more" diff --git a/src/status_im/ui/components/chat_icon/screen.cljs b/src/status_im/ui/components/chat_icon/screen.cljs index ec8e4c7e07..2848f7a253 100644 --- a/src/status_im/ui/components/chat_icon/screen.cljs +++ b/src/status_im/ui/components/chat_icon/screen.cljs @@ -1,121 +1,118 @@ (ns status-im.ui.components.chat-icon.screen - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :refer [subscribe dispatch]] - [status-im.ui.components.react :refer [view - text - image]] - [status-im.ui.components.chat-icon.styles :as st] - [status-im.ui.components.styles :refer [default-chat-color]] + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [status-im.ui.components.react :as react] + [status-im.ui.components.chat-icon.styles :as styles] + [status-im.ui.components.styles :as components.styles] [status-im.react-native.resources :as resources] - [status-im.constants :refer [console-chat-id]] - [clojure.string :as s])) + [clojure.string :as string] + [status-im.i18n :as i18n])) (defn default-chat-icon [name styles] - [view (:default-chat-icon styles) - [text {:style (:default-chat-icon-text styles)} + [react/view (:default-chat-icon styles) + [react/text {:style (:default-chat-icon-text styles)} (first name)]]) (defn chat-icon [photo-path {:keys [size accessibility-label]}] - (let [photo (if (s/starts-with? photo-path "contacts://") - (->> (s/replace photo-path #"contacts://" "") + (let [photo (if (string/starts-with? photo-path "contacts://") + (->> (string/replace photo-path #"contacts://" "") (keyword) (get resources/contacts)) {:uri photo-path})] - [image {:source photo - :style (st/image-style size) - :accessibility-label (or accessibility-label :chat-icon)}])) + [react/image {:source photo + :style (styles/image-style size) + :accessibility-label (or accessibility-label :chat-icon)}])) (defn dapp-badge [{:keys [online-view-wrapper online-view online-dot-left online-dot-right]}] - [view online-view-wrapper - [view online-view - [view - [view online-dot-left] - [view online-dot-right]]]]) + [react/view online-view-wrapper + [react/view online-view + [react/view + [react/view online-dot-left] + [react/view online-dot-right]]]]) (defview pending-contact-badge [chat-id {:keys [pending-wrapper pending-outer-circle pending-inner-circle]}] - [pending-contact? [:get-in [:contacts/contacts chat-id :pending?]]] - (when pending-contact? - [view pending-wrapper - [view pending-outer-circle - [view pending-inner-circle]]])) + (letsubs [pending-contact? [:get-in [:contacts/contacts chat-id :pending?]]] + (when pending-contact? + [react/view pending-wrapper + [react/view pending-outer-circle + [react/view pending-inner-circle]]]))) -(defview chat-icon-view [chat-id group-chat name online styles & [hide-dapp?]] - [photo-path [:get-chat-photo chat-id] - dapp? [:get-in [:contacts/contacts chat-id :dapp?]]] - [view (:container styles) - (if-not (s/blank? photo-path) - [chat-icon photo-path styles] - [default-chat-icon name styles]) - (when (and dapp? (not hide-dapp?)) - [dapp-badge styles]) - [pending-contact-badge chat-id styles]]) +(defview chat-icon-view [chat-id _group-chat name _online styles & [hide-dapp?]] + (letsubs [photo-path [:get-chat-photo chat-id] + dapp? [:get-in [:contacts/contacts chat-id :dapp?]]] + [react/view (:container styles) + (if-not (string/blank? photo-path) + [chat-icon photo-path styles] + [default-chat-icon name styles]) + (when (and dapp? (not hide-dapp?)) + [dapp-badge styles]) + [pending-contact-badge chat-id styles]])) (defn chat-icon-view-chat-list [chat-id group-chat name color online] [chat-icon-view chat-id group-chat name online - {:container st/container-chat-list - :online-view-wrapper st/online-view-wrapper - :online-view st/online-view - :online-dot-left st/online-dot-left - :online-dot-right st/online-dot-right - :pending-wrapper st/pending-wrapper - :pending-outer-circle st/pending-outer-circle - :pending-inner-circle st/pending-inner-circle + {:container styles/container-chat-list + :online-view-wrapper styles/online-view-wrapper + :online-view styles/online-view + :online-dot-left styles/online-dot-left + :online-dot-right styles/online-dot-right + :pending-wrapper styles/pending-wrapper + :pending-outer-circle styles/pending-outer-circle + :pending-inner-circle styles/pending-inner-circle :size 40 - :chat-icon st/chat-icon-chat-list - :default-chat-icon (st/default-chat-icon-chat-list color) - :default-chat-icon-text st/default-chat-icon-text}]) + :chat-icon styles/chat-icon-chat-list + :default-chat-icon (styles/default-chat-icon-chat-list color) + :default-chat-icon-text styles/default-chat-icon-text}]) -(defn chat-icon-view-action [chat-id group-chat name color online] +(defn chat-icon-view-action [chat-id group-chat name _color online] ^{:key chat-id} [chat-icon-view chat-id group-chat name online - {:container st/container-chat-list - :online-view-wrapper st/online-view-wrapper - :online-view st/online-view - :online-dot-left st/online-dot-left - :online-dot-right st/online-dot-right + {:container styles/container-chat-list + :online-view-wrapper styles/online-view-wrapper + :online-view styles/online-view + :online-dot-left styles/online-dot-left + :online-dot-right styles/online-dot-right :size 40 - :chat-icon st/chat-icon-chat-list - :default-chat-icon (st/default-chat-icon-chat-list default-chat-color) - :default-chat-icon-text st/default-chat-icon-text}]) + :chat-icon styles/chat-icon-chat-list + :default-chat-icon (styles/default-chat-icon-chat-list components.styles/default-chat-color) + :default-chat-icon-text styles/default-chat-icon-text}]) (defn chat-icon-view-menu-item [chat-id group-chat name color online] ^{:key chat-id} [chat-icon-view chat-id group-chat name online - {:container st/container-menu-item - :online-view-wrapper st/online-view-menu-wrapper - :online-view st/online-view-menu-item - :online-dot-left st/online-dot-left-menu-item - :online-dot-right st/online-dot-right-menu-item - :pending-wrapper st/pending-view-menu-wrapper - :pending-outer-circle st/pending-outer-circle - :pending-inner-circle st/pending-inner-circle + {:container styles/container-menu-item + :online-view-wrapper styles/online-view-menu-wrapper + :online-view styles/online-view-menu-item + :online-dot-left styles/online-dot-left-menu-item + :online-dot-right styles/online-dot-right-menu-item + :pending-wrapper styles/pending-view-menu-wrapper + :pending-outer-circle styles/pending-outer-circle + :pending-inner-circle styles/pending-inner-circle :size 24 - :chat-icon st/chat-icon-menu-item - :default-chat-icon (st/default-chat-icon-view-action color) - :default-chat-icon-text st/default-chat-icon-text} + :chat-icon styles/chat-icon-menu-item + :default-chat-icon (styles/default-chat-icon-view-action color) + :default-chat-icon-text styles/default-chat-icon-text} true]) (defn chat-icon-message-status [chat-id group-chat name color online] ^{:key chat-id} [chat-icon-view chat-id group-chat name online - {:container st/container-message-status - :online-view-wrapper st/online-view-wrapper - :online-view st/online-view - :online-dot-left st/online-dot-left - :online-dot-right st/online-dot-right - :pending-wrapper st/pending-wrapper - :pending-outer-circle st/pending-outer-circle - :pending-inner-circle st/pending-inner-circle + {:container styles/container-message-status + :online-view-wrapper styles/online-view-wrapper + :online-view styles/online-view + :online-dot-left styles/online-dot-left + :online-dot-right styles/online-dot-right + :pending-wrapper styles/pending-wrapper + :pending-outer-circle styles/pending-outer-circle + :pending-inner-circle styles/pending-inner-circle :size 64 - :chat-icon st/chat-icon-message-status - :default-chat-icon (st/default-chat-icon-message-status color) - :default-chat-icon-text st/message-status-icon-text}]) + :chat-icon styles/chat-icon-message-status + :default-chat-icon (styles/default-chat-icon-message-status color) + :default-chat-icon-text styles/message-status-icon-text}]) (defn contact-icon-view [{:keys [photo-path name dapp?]} {:keys [container] :as styles}] (let [photo-path photo-path] - [view container - (if-not (s/blank? photo-path) + [react/view container + (if-not (string/blank? photo-path) [chat-icon photo-path styles] [default-chat-icon name styles]) (when dapp? @@ -123,32 +120,32 @@ (defn contact-icon-contacts-tab [contact] [contact-icon-view contact - {:container st/container-chat-list - :online-view-wrapper st/online-view-wrapper - :online-view st/online-view - :online-dot-left st/online-dot-left - :online-dot-right st/online-dot-right + {:container styles/container-chat-list + :online-view-wrapper styles/online-view-wrapper + :online-view styles/online-view + :online-dot-left styles/online-dot-left + :online-dot-right styles/online-dot-right :size 40 - :chat-icon st/chat-icon-chat-list - :default-chat-icon (st/default-chat-icon-chat-list default-chat-color) - :default-chat-icon-text st/default-chat-icon-text}]) + :chat-icon styles/chat-icon-chat-list + :default-chat-icon (styles/default-chat-icon-chat-list components.styles/default-chat-color) + :default-chat-icon-text styles/default-chat-icon-text}]) (defn profile-icon-view [photo-path name color edit? size] (let [styles {:container {:width size :height size} - :online-view st/online-view-profile - :online-dot-left st/online-dot-left-profile - :online-dot-right st/online-dot-right-profile + :online-view styles/online-view-profile + :online-dot-left styles/online-dot-left-profile + :online-dot-right styles/online-dot-right-profile :size size - :chat-icon st/chat-icon-profile - :default-chat-icon (st/default-chat-icon-profile color) - :default-chat-icon-text st/default-chat-icon-text}] - [view (:container styles) + :chat-icon styles/chat-icon-profile + :default-chat-icon (styles/default-chat-icon-profile color) + :default-chat-icon-text styles/default-chat-icon-text}] + [react/view (:container styles) (when edit? - [view (st/profile-icon-mask size)]) + [react/view (styles/profile-icon-mask size)]) (when edit? - [view (st/profile-icon-edit-text-containter size) - [text {:style st/profile-icon-edit-text} - "Edit"]]) + [react/view (styles/profile-icon-edit-text-containter size) + [react/text {:style styles/profile-icon-edit-text} + (i18n/label :t/edit)]]) (if (and photo-path (seq photo-path)) [chat-icon photo-path styles] [default-chat-icon name styles])])) @@ -157,6 +154,6 @@ (defn my-profile-icon [{{:keys [photo-path name]} :account edit? :edit?}] - (let [color default-chat-color - size (if edit? 70 56)] + (let [color components.styles/default-chat-color + size 56] [profile-icon-view photo-path name color edit? size])) diff --git a/src/status_im/ui/components/colors.cljs b/src/status_im/ui/components/colors.cljs index 6d677f5017..cda2d3af03 100644 --- a/src/status_im/ui/components/colors.cljs +++ b/src/status_im/ui/components/colors.cljs @@ -6,4 +6,5 @@ (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 \ No newline at end of file +(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions +(def light-gray "#eef2f5") ;; Used as a background or shadow \ No newline at end of file diff --git a/src/status_im/ui/components/common/common.cljs b/src/status_im/ui/components/common/common.cljs index 07f0eda708..6740693428 100644 --- a/src/status_im/ui/components/common/common.cljs +++ b/src/status_im/ui/components/common/common.cljs @@ -6,7 +6,8 @@ [status-im.ui.components.common.styles :as styles] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.platform :as platform] - [status-im.i18n :as i18n])) + [status-im.i18n :as i18n] + [re-frame.core :as re-frame])) (defn top-shadow [] (when platform/android? @@ -72,3 +73,15 @@ (if (ethereum/testnet? network-id) (i18n/label :t/testnet-text {:testnet (get-in ethereum/chains [(ethereum/chain-id->chain-keyword network-id) :name] "Unknown")}) (i18n/label :t/mainnet-text))]]])) + +(defn icon-or-label + "Renders a touchable icon on Android or a label or iOS." + [action-opts label-kw label-style icon-id icon-opts] + [react/touchable-highlight action-opts + (if platform/ios? + [react/view + [react/text {:style (merge styles/label-action-text label-style)} + (i18n/label label-kw)]] + [react/view styles/icon-action + [vector-icons/icon icon-id icon-opts]])]) + diff --git a/src/status_im/ui/components/common/styles.cljs b/src/status_im/ui/components/common/styles.cljs index ac5c851300..e7d18b8a8f 100644 --- a/src/status_im/ui/components/common/styles.cljs +++ b/src/status_im/ui/components/common/styles.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.components.common.styles (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.ui.components.styles :as styles])) + (:require [status-im.ui.components.styles :as styles] + [status-im.ui.components.colors :as colors])) (def gradient-top {:flexDirection :row @@ -101,4 +102,17 @@ :border-radius (/ 40 2) :background-color styles/color-green-4 :align-items :center - :justify-content :center}) \ No newline at end of file + :justify-content :center}) + +(defstyle label-action-text + {:padding-right 16 + :color colors/blue + :ios {:font-size 15} + :android {:font-size 14}}) + +(def icon-action + {:width 40 + :height 40 + :margin-right 4 + :align-items :center + :justify-content :center}) \ No newline at end of file diff --git a/src/status_im/ui/components/context_menu.cljs b/src/status_im/ui/components/context_menu.cljs index 86ca9b71c9..f258d1aff2 100644 --- a/src/status_im/ui/components/context_menu.cljs +++ b/src/status_im/ui/components/context_menu.cljs @@ -39,8 +39,9 @@ (def list-selection-fn (:list-selection-fn platform-specific)) -(defn open-ios-menu [options] +(defn open-ios-menu [title options] (list-selection-fn {:options options + :title title :callback (fn [index] (when (< index (count options)) (when-let [handler (:value (nth options index))] @@ -50,7 +51,7 @@ (defn context-menu [trigger options & custom-styles trigger-style] (if ios? [rn/touchable-highlight {:style trigger-style - :on-press #(open-ios-menu options)} + :on-press #(open-ios-menu nil options)} [rn/view trigger]] [menu {:onSelect #(when % (do (%) nil))} @@ -61,3 +62,9 @@ [menu-option {:value value} [rn/text {:style (merge (context-menu-text destructive?) style)} (:text option)]])]])) + +(defn modal-menu [trigger style title options] + [rn/touchable-highlight {:style style + :on-press #(open-ios-menu title options)} + [rn/view + trigger]]) diff --git a/src/status_im/ui/components/qr_code.cljs b/src/status_im/ui/components/qr_code.cljs deleted file mode 100644 index dc860dcda5..0000000000 --- a/src/status_im/ui/components/qr_code.cljs +++ /dev/null @@ -1,8 +0,0 @@ -(ns status-im.ui.components.qr-code - (:require [reagent.core :as r] - [status-im.react-native.js-dependencies :as rn-dependencies])) - -(defn qr-code [props] - (r/create-element - rn-dependencies/qr-code - (clj->js (merge {:inverted true} props)))) diff --git a/src/status_im/ui/components/qr_code_viewer/styles.cljs b/src/status_im/ui/components/qr_code_viewer/styles.cljs new file mode 100644 index 0000000000..7239a3818b --- /dev/null +++ b/src/status_im/ui/components/qr_code_viewer/styles.cljs @@ -0,0 +1,97 @@ +(ns status-im.ui.components.qr-code-viewer.styles + (:require [status-im.ui.components.colors :as colors]) + (:require-macros [status-im.utils.styles :refer [defstyle]])) + +(def qr-code-hint + {:color colors/gray + :padding-bottom 24 + :text-align :center}) + +(def qr-code-padding + 15) + +(defn qr-code-container [dimensions] + {:background-color colors/white + :width (:width dimensions) + :align-items :center + :justify-content :center + :padding qr-code-padding + :border-radius 8}) + +(def toolbar-done-text-ios + {:color colors/blue + :letter-spacing -0.2 + :font-size 17}) + +(defstyle name-container + {:flex 0.6 + :flex-direction :column + :ios {:align-items :center} + :android {:margin-left 15}}) + +(defstyle name-text + {:color colors/black + :font-size 17 + :ios {:letter-spacing -0.2}}) + +(def address-text + {:color colors/white + :font-size 12}) + +(def toolbar-action-container + {:flex 0.2 + :flex-direction :column + :align-items :center + :justify-content :center}) + +(def toolbar-action-icon-container + {:width 40 + :height 40 + :margin-right 16 + :align-items :center + :justify-content :center}) + +(def wallet-qr-code + {:flex-grow 1 + :flex-direction :column}) + +(def account-toolbar + {:background-color colors/white}) + +(def toolbar-contents + {:flex-grow 1 + :flex-direction :row + :height 55 + :align-items :center + :justify-content :center}) + +(def qr-code + {:background-color colors/light-gray + :flex-grow 1 + :align-items :center + :justify-content :center}) + +(def footer + {:background-color colors/light-gray + :flex-direction :row + :justify-content :center + :padding-bottom 50}) + +(def wallet-info + {:align-items :center + :padding-bottom 20}) + +(def hash-value-type + {:color colors/black + :padding-bottom 5}) + +(def hash-value-text + {:color colors/black + :margin-horizontal 60 + :text-align :center + :font-size 15 + :letter-spacing -0.2 + :line-height 20}) + +(def done-button-text + {:color colors/white}) diff --git a/src/status_im/ui/components/qr_code_viewer/views.cljs b/src/status_im/ui/components/qr_code_viewer/views.cljs new file mode 100644 index 0000000000..0cf2e152d5 --- /dev/null +++ b/src/status_im/ui/components/qr_code_viewer/views.cljs @@ -0,0 +1,59 @@ +(ns status-im.ui.components.qr-code-viewer.views + (:require [re-frame.core :as re-frame] + [status-im.ui.components.react :as react] + [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.status-bar.view :as status-bar] + [status-im.ui.components.list-selection :as list-selection] + [status-im.ui.components.qr-code-viewer.styles :as styles] + [status-im.ui.components.common.common :as common] + [status-im.ui.components.common.styles :as common.styles] + [status-im.utils.platform :as platform] + [status-im.i18n :as i18n] + [status-im.react-native.js-dependencies :as rn-dependencies] + [reagent.core :as r]) + (:require-macros [status-im.utils.views :refer [defview letsubs]])) + +(defn qr-code [props] + (r/create-element + rn-dependencies/qr-code + (clj->js (merge {:inverted true} props)))) + +(defn qr-viewer-toolbar [name qr-value] + [react/view styles/account-toolbar + [react/view styles/toolbar-contents + [react/view styles/toolbar-action-container + [common/icon-or-label {:on-press #(re-frame/dispatch [:navigate-back])} + :t/done styles/toolbar-done-text-ios :icons/close {:color :black}]] + [react/view styles/name-container + [react/text {:style styles/name-text + :number-of-lines 1} name]] + [react/view styles/toolbar-action-container + [react/touchable-highlight {:on-press #(list-selection/open-share {:message qr-value})} + [react/view styles/toolbar-action-icon-container + [vector-icons/icon :icons/share {:color :black}]]]]]]) + +(defn qr-viewer-body [qr-value dimensions] + [react/view {:style styles/qr-code + :on-layout #(let [layout (.. % -nativeEvent -layout)] + (re-frame/dispatch [:set-in [:qr-modal :dimensions] {:width (* 0.7 (.-width layout)) + :height (.-height layout)}]))} + [react/text {:style styles/qr-code-hint} (i18n/label :t/qr-code-public-key-hint)] + (when (:width dimensions) + [react/view {:style (styles/qr-code-container dimensions)} + [qr-code {:value qr-value + :size (- (min (:width dimensions) + (:height dimensions)) + (* 2 styles/qr-code-padding))}]])]) + +(defn qr-viewer-footer [qr-value] + [react/view styles/footer + [react/view styles/wallet-info + [react/text {:style styles/hash-value-text} qr-value]]]) + +(defview qr-viewer [] + (letsubs [{:keys [qr-value dimensions contact]} [:get :qr-modal]] + [react/view styles/wallet-qr-code + [status-bar/status-bar {:type :modal}] + [qr-viewer-toolbar (:name contact) qr-value] + [qr-viewer-body qr-value dimensions] + [qr-viewer-footer qr-value]])) diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 84b7a0f4a1..4f61562504 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -48,7 +48,8 @@ :networks/networks constants/default-networks :inbox/wnode constants/default-wnode :inbox/topic constants/inbox-topic - :inbox/password constants/inbox-password}) + :inbox/password constants/inbox-password + :my-profile/editing? false}) ;;;;GLOBAL @@ -123,6 +124,7 @@ :my-profile/drawer :my-profile/profile :my-profile/default-name + :my-profile/editing? :networks/selected-network :networks/networks :node/after-start diff --git a/src/status_im/ui/screens/profile/edit/views.cljs b/src/status_im/ui/screens/profile/edit/views.cljs deleted file mode 100644 index f0295c9751..0000000000 --- a/src/status_im/ui/screens/profile/edit/views.cljs +++ /dev/null @@ -1,104 +0,0 @@ -(ns status-im.ui.screens.profile.edit.views - (:require [cljs.spec.alpha :as spec] - [clojure.string :as string] - [re-frame.core :refer [dispatch]] - [reagent.core :as reagent] - [status-im.ui.components.camera :as camera] - [status-im.ui.components.chat-icon.screen :refer [my-profile-icon]] - [status-im.ui.components.context-menu :refer [context-menu]] - [status-im.ui.components.react :as react] - [status-im.ui.components.status-bar.view :refer [status-bar]] - [status-im.ui.components.sticky-button :refer [sticky-button]] - [status-im.ui.components.text-input-with-label.view :refer [text-input-with-label]] - [status-im.ui.components.toolbar.view :as toolbar] - [status-im.i18n :refer [label]] - [status-im.ui.screens.profile.db :as db] - [status-im.ui.screens.profile.events :as profile.events] - [status-im.ui.screens.profile.styles :as styles] - [status-im.ui.screens.profile.views :refer [colorize-status-hashtags]] - [status-im.utils.utils :as utils :refer [clean-text]]) - (:require-macros [status-im.utils.views :refer [defview letsubs]])) - -(defn edit-my-profile-toolbar [] - [toolbar/toolbar {} - toolbar/default-nav-back - [toolbar/content-title (label :t/edit-profile)]]) - -(defview profile-name-input [] - (letsubs [profile-name [:my-profile/get :name] - placeholder [:get :my-profile/default-name]] - [react/view - [text-input-with-label - {:label (label :t/name) - :default-value profile-name - :on-focus #(dispatch [:my-profile/edit-profile]) - :on-change-text #(dispatch [:my-profile/update-name %])}]])) - - -(def profile-icon-options - [{:text (label :t/image-source-gallery) - :value #(dispatch [:my-profile/update-picture])} - {:text (label :t/image-source-make-photo) - :value (fn [] - (dispatch [:request-permissions - [:camera :write-external-storage] - (fn [] - (camera/request-access - #(if % - (dispatch [:navigate-to :profile-photo-capture]) - (utils/show-popup (label :t/error) - (label :t/camera-access-error)))))]))}]) - -(defn edit-profile-badge [contact] - [react/view styles/edit-profile-badge - [react/view styles/edit-profile-icon-container - [context-menu - [my-profile-icon {:account contact - :edit? true}] - profile-icon-options - styles/context-menu-custom-styles]] - [react/view styles/edit-profile-name-container - [profile-name-input]]]) - -(defview edit-profile-status [] - (letsubs [edit-status? [:my-profile/get :edit-status?] - status [:my-profile/get :status]] - [react/view styles/edit-profile-status - [react/scroll-view - (if edit-status? - [react/text-input - {:auto-focus (if edit-status? true false) - :multiline true - :max-length 140 - :placeholder (label :t/status) - :style styles/profile-status-input - :on-change-text #(dispatch [:my-profile/update-status %]) - :default-value status}] - [react/touchable-highlight {:on-press #(dispatch [:my-profile/edit-profile :status])} - [react/view - (if (string/blank? status) - [react/text {:style styles/add-a-status} - (label :t/status)] - [react/text {:style styles/profile-status-text} - (colorize-status-hashtags status)])]])]])) - -(defn status-prompt [{:keys [status]}] - (when (or (nil? status) (string/blank? status)) - [react/view styles/status-prompt - [react/text {:style styles/status-prompt-text} - (colorize-status-hashtags (label :t/status-prompt))]])) - -(defview edit-my-profile [] - (letsubs [current-account [:get-current-account] - changed-account [:get :my-profile/profile] - profile-changed? [:my-profile/changed?] - valid-name? [:my-profile/valid-name?]] - [react/keyboard-avoiding-view {:style styles/profile} - [status-bar] - [edit-my-profile-toolbar] - [react/scroll-view styles/edit-my-profile-form - [edit-profile-badge changed-account] - [edit-profile-status] - [status-prompt changed-account]] - (when (and valid-name? profile-changed?) - [sticky-button (label :t/save) #(dispatch [:my-profile/save-profile])])])) diff --git a/src/status_im/ui/screens/profile/events.cljs b/src/status_im/ui/screens/profile/events.cljs index 440211c7fe..c2fcb1983b 100644 --- a/src/status_im/ui/screens/profile/events.cljs +++ b/src/status_im/ui/screens/profile/events.cljs @@ -82,8 +82,7 @@ (assoc-in [:my-profile/profile :edit-status?] edit-status?) (update-in [:my-profile/profile] #(merge (select-keys (get-current-account db) db/account-profile-keys) %)))] - {:db new-db - :dispatch [:navigate-to :edit-my-profile]}))) + {:db new-db}))) (defn valid-name? [name] (spec/valid? :profile/name name)) @@ -139,7 +138,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)) + (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 @@ -172,6 +171,11 @@ (status-change {:old-status old-status :status status})))))) +(handlers/register-handler-fx + :my-profile/start-editing-profile + (fn [{:keys [db]} []] + {:db (assoc db :my-profile/editing? true)})) + (handlers/register-handler-fx :my-profile/save-profile (fn [{:keys [db now]} _] @@ -179,10 +183,11 @@ {old-status :status} (get accounts current-account-id) {:keys [status photo-path]} (:my-profile/profile db) cleaned-name (clean-name db :my-profile/profile) - cleaned-edit {:name cleaned-name - :status status - :photo-path photo-path - :last-updated now}] + cleaned-edit (merge {:name cleaned-name + :status status + :last-updated now} + (if photo-path + {:photo-path photo-path}))] (-> (clear-profile {:db db}) (accounts-events/account-update cleaned-edit) (status-change {:old-status old-status diff --git a/src/status_im/ui/screens/profile/navigation.cljs b/src/status_im/ui/screens/profile/navigation.cljs index 828349443b..dc14adaa20 100644 --- a/src/status_im/ui/screens/profile/navigation.cljs +++ b/src/status_im/ui/screens/profile/navigation.cljs @@ -1,9 +1,12 @@ (ns status-im.ui.screens.profile.navigation (:require [status-im.ui.screens.navigation :as navigation])) -(defmethod navigation/preload-data! :qr-code-view +;;TODO(goranjovic) - replace this with an atomic navigation event that calls functions, not dispatch +;; possibly use the generic event, see https://github.com/status-im/status-react/issues/2987 +(defmethod navigation/preload-data! :qr-viewer [{:accounts/keys [current-account-id] :as db} [_ _ {:keys [contact qr-source qr-value]}]] (update db :qr-modal #(merge % {:contact (or contact (get-in db [:accounts/accounts current-account-id])) :qr-source qr-source :qr-value qr-value}))) + diff --git a/src/status_im/ui/screens/profile/qr_code/styles.cljs b/src/status_im/ui/screens/profile/qr_code/styles.cljs deleted file mode 100644 index cce348887f..0000000000 --- a/src/status_im/ui/screens/profile/qr_code/styles.cljs +++ /dev/null @@ -1,103 +0,0 @@ -(ns status-im.ui.screens.profile.qr-code.styles - (:require [status-im.ui.components.styles :refer [color-white]])) - -(def photo-container - {:flex 0.2 - :flexDirection :column - :alignItems :center - :justifyContent :center}) - -(def account-photo-container - {:flex 1 - :width 36 - :height 36 - :alignItems :center - :justifyContent :center}) - -(def qr-photo-container - (merge photo-container - {:margin-left 8 - :margin-right 4})) - -(defn qr-code-container [dimensions] - {:background-color "white" - :width (:width dimensions) - :align-items :center - :justify-content :center - :padding 40}) - -(def photo-image - {:width 36 - :height 36 - :border-radius 18}) - -(def name-container - {:flex 1 - :flexDirection :column}) - -(def name-text - {:color color-white - :fontSize 16}) - -(def address-text - {:color color-white - :fontSize 12}) - -(def online-container - {:flex 0.2 - :flexDirection :column - :alignItems :center - :justifyContent :center}) - -(def online-image-container - {:width 40 - :height 40 - :margin-right 4 - :align-items :center - :justify-content :center}) - -(def wallet-qr-code - {:flex-grow 1 - :flex-direction :column}) - -(def account-toolbar - {:background-color "#2f3031"}) - -(def wallet-account-container - {:flex-grow 1 - :flexDirection :row - :height 69 - :alignItems :center - :justifyContent :center}) - -(def qr-code - {:background-color "#2f3031" - :flex-grow 1 - :align-items :center - :justify-content :center}) - -(def footer - {:background-color "#2f3031"}) - -(def wallet-info - {:align-items :center - :padding-bottom 20 - :padding-top 20}) - -(def wallet-name-text - {:color color-white - :padding-bottom 5}) - -(def wallet-address-text - {:color "#999999"}) - -(def done-button - {:flex-grow 1 - :flex-direction :column - :align-items :center - :justify-content :center - :height 51 - :background-color "#7597e4"}) - -(def done-button-text - {:color color-white}) diff --git a/src/status_im/ui/screens/profile/qr_code/views.cljs b/src/status_im/ui/screens/profile/qr_code/views.cljs deleted file mode 100644 index 742bf26148..0000000000 --- a/src/status_im/ui/screens/profile/qr_code/views.cljs +++ /dev/null @@ -1,51 +0,0 @@ -(ns status-im.ui.screens.profile.qr-code.views - (:require [clojure.string :as string] - [re-frame.core :refer [dispatch]] - [status-im.ui.components.qr-code :refer [qr-code]] - [status-im.ui.components.react :as react] - [status-im.ui.components.icons.vector-icons :as vi] - [status-im.ui.components.status-bar.view :refer [status-bar]] - [status-im.i18n :refer [label]] - [status-im.ui.screens.profile.qr-code.styles :as styles] - [status-im.utils.money :as money]) - (:require-macros [status-im.utils.views :refer [defview letsubs]])) - -(defview qr-code-view [] - (letsubs [{:keys [photo-path address name]} [:get-in [:qr-modal :contact]] - {:keys [qr-source qr-value dimensions]} [:get :qr-modal] - chain-id [:get-network-id]] - [react/view styles/wallet-qr-code - [status-bar {:type :modal}] - [react/view styles/account-toolbar - [react/view styles/wallet-account-container - [react/view styles/qr-photo-container - [react/view styles/account-photo-container - [react/image {:source {:uri (if (string/blank? photo-path) :avatar photo-path)} - :style styles/photo-image}]]] - [react/view styles/name-container - [react/text {:style styles/name-text - :number-of-lines 1} name]] - [react/view styles/online-container - [react/touchable-highlight {:onPress #(dispatch [:navigate-back])} - [react/view styles/online-image-container - [vi/icon :icons/close {:color :white}]]]]]] - [react/view {:style styles/qr-code - :on-layout #(let [layout (.. % -nativeEvent -layout)] - (dispatch [:set-in [:qr-modal :dimensions] {:width (.-width layout) - :height (.-height layout)}]))} - (when (:width dimensions) - [react/view {:style (styles/qr-code-container dimensions)} - [qr-code {:value qr-value - :size (- (min (:width dimensions) - (:height dimensions)) - 80)}]])] - [react/view styles/footer - (if (= :address qr-source) - [react/view styles/wallet-info - [react/text {:style styles/wallet-name-text} (label :t/main-wallet)] - [react/text {:style styles/wallet-address-text} address]] - [react/view styles/wallet-info - [react/text {:style styles/wallet-name-text} (label :t/public-key)]]) - [react/touchable-highlight {:onPress #(dispatch [:navigate-back])} - [react/view styles/done-button - [react/text {:style styles/done-button-text} (label :t/done)]]]]])) diff --git a/src/status_im/ui/screens/profile/styles.cljs b/src/status_im/ui/screens/profile/styles.cljs index 471d247f3c..3a2f126941 100644 --- a/src/status_im/ui/screens/profile/styles.cljs +++ b/src/status_im/ui/screens/profile/styles.cljs @@ -4,12 +4,6 @@ [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 colors/white @@ -19,10 +13,6 @@ {:background-color colors/white :padding 16}) -(def edit-my-profile-form - {:background-color colors/white - :flex 1}) - (defstyle profile-info-container {:background-color colors/white}) @@ -54,20 +44,9 @@ :justify-content :center :align-items :center}) -(def edit-profile-badge - {:flex-direction :row - :padding-left 24}) - (def context-menu-custom-styles {:optionsContainer {:margin-top 78}}) -(def edit-profile-name-container - {:flex 1 - :padding-top 30}) - -(def edit-profile-icon-container - {:padding-top 25}) - (def edit-name-title {:color colors/gray :ios {:font-size 13 @@ -75,10 +54,18 @@ :android {:font-size 12}}) (defstyle profile-name-text - {:margin-top 8 - :font-size 15 + {:padding-vertical 14 + :font-size 15 + :text-align :center + :ios {:letter-spacing -0.2} + :android {:color colors/black}}) + +(defstyle profile-name-input-text + {:font-size 15 :text-align :center - :ios {:letter-spacing -0.2} + :ios {:letter-spacing -0.2 + :height 46 + :width 800} :android {:color colors/black}}) (def profile-badge-name-container diff --git a/src/status_im/ui/screens/profile/views.cljs b/src/status_im/ui/screens/profile/views.cljs index 33b772c3d7..1989bb924f 100644 --- a/src/status_im/ui/screens/profile/views.cljs +++ b/src/status_im/ui/screens/profile/views.cljs @@ -5,6 +5,7 @@ [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.common.styles :as common.styles] [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] @@ -22,7 +23,8 @@ [status-im.utils.config :as config] [status-im.utils.platform :as platform] [status-im.protocol.core :as protocol] - [re-frame.core :as re-frame]) + [re-frame.core :as re-frame] + [status-im.ui.components.camera :as camera]) (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defn my-profile-toolbar [] @@ -30,11 +32,18 @@ nil [toolbar/content-title ""] [react/touchable-highlight - {:on-press #(re-frame/dispatch [:my-profile/edit-profile])} + {:on-press #(re-frame/dispatch [:my-profile/start-editing-profile])} [react/view - [react/text {:style styles/toolbar-edit-text + [react/text {:style common.styles/label-action-text :uppercase? component.styles/uppercase?} (i18n/label :t/edit)]]]]) +(defn my-profile-edit-toolbar [] + [toolbar/toolbar {} + nil + [toolbar/content-title ""] + [common/icon-or-label {:on-press #(re-frame/dispatch [:my-profile/save-profile])} + :t/done {} :icons/ok {:color colors/blue}]]) + (defn profile-toolbar [contact] [toolbar/toolbar {} toolbar/default-nav-back @@ -66,6 +75,45 @@ [react/text {:style styles/profile-activity-status-text} (online-text last-online)]])]]) + +(defn profile-name-input [name] + [react/view + [react/text-input + {:style styles/profile-name-input-text + :placeholder "" + :default-value name + :auto-focus true + :on-focus #(re-frame/dispatch [:my-profile/edit-profile]) + :on-change-text #(re-frame/dispatch [:my-profile/update-name %])}]]) + +(def profile-icon-options + [{:text (i18n/label :t/image-source-gallery) + :value #(re-frame/dispatch [:my-profile/update-picture])} + {:text (i18n/label :t/image-source-make-photo) + :value (fn [] + (re-frame/dispatch [:request-permissions + [:camera :write-external-storage] + (fn [] + (camera/request-access + #(if % + (re-frame/dispatch [:navigate-to :profile-photo-capture]) + (utils/show-popup (i18n/label :t/error) + (i18n/label :t/camera-access-error)))))]))}]) + +(defn profile-badge-edit [{:keys [name last-online] :as account}] + [react/view styles/profile-badge + [context-menu/modal-menu + [chat-icon.screen/my-profile-icon {:account account + :edit? true}] + {} (i18n/label :t/image-source-title) + profile-icon-options] + [react/view styles/profile-badge-name-container + [profile-name-input name] + (when-not (nil? last-online) + [react/view styles/profile-activity-status-container + [react/text {:style styles/profile-activity-status-text} + (online-text last-online)]])]]) + (defn profile-actions [{:keys [pending? whisper-identity dapp?]} chat-id] [react/view action-button.styles/actions-list (if pending? @@ -108,9 +156,9 @@ styles/profile-info-item-button])]) (defn show-qr [contact qr-source qr-value] - #(re-frame/dispatch [:navigate-to-modal :qr-code-view {:contact contact - :qr-source qr-source - :qr-value qr-value}])) + #(re-frame/dispatch [:navigate-to :qr-viewer {:contact contact + :qr-source qr-source + :qr-value qr-value}])) (defn profile-options [contact k text] (into [] @@ -249,12 +297,18 @@ [vector-icons/icon :icons/qr {:color colors/blue}]]]]) (defview my-profile [] - (letsubs [{:keys [public-key] :as current-account} [:get-current-account]] + (letsubs [{:keys [public-key] :as current-account} [:get-current-account] + editing? [:get :my-profile/editing?] + changed-account [:get :my-profile/profile]] [react/view styles/profile - [my-profile-toolbar] + (if editing? + [my-profile-edit-toolbar] + [my-profile-toolbar]) [react/scroll-view [react/view styles/profile-form - [profile-badge current-account]] + (if editing? + [profile-badge-edit (merge current-account changed-account)] + [profile-badge current-account])] [react/view action-button.styles/actions-list [share-contact-code current-account public-key]] [react/view styles/profile-info-container diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 87447fffb4..108fa0ffe7 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -29,10 +29,9 @@ add-participants-toggle-list]] [status-im.ui.screens.group.reorder.views :refer [reorder-groups]] - [status-im.ui.screens.profile.views :refer [profile my-profile]] - [status-im.ui.screens.profile.edit.views :refer [edit-my-profile]] + [status-im.ui.screens.profile.views :as profile] [status-im.ui.screens.profile.photo-capture.views :refer [profile-photo-capture]] - [status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]] + [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.screens.wallet.send.views :refer [send-transaction send-transaction-modal]] [status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]] @@ -91,8 +90,7 @@ :new-contact new-contact :qr-scanner qr-scanner :chat chat - :profile profile - :edit-my-profile edit-my-profile + :profile profile/profile :discover-all-recent discover-recent/discover-all-recent :discover-all-popular-hashtags discover-popular/discover-all-popular-hashtags :discover-search-results discover-search/discover-search-results @@ -107,6 +105,7 @@ :paste-json-text paste-json-text :add-rpc-url add-rpc-url :network-details network-details + :qr-viewer qr-code-viewer/qr-viewer (throw (str "Unknown view: " current-view)))] [(if android? menu-context view) common-styles/flex [view common-styles/flex @@ -118,7 +117,6 @@ :on-request-close #(dispatch [:navigate-back])} (let [component (case modal-view :qr-scanner qr-scanner - :qr-code-view qr-code-view :recover-modal recover-modal :contact-list-modal contact-list-modal :wallet-transactions-filter wallet-transactions/filter-history diff --git a/src/status_im/ui/screens/wallet/request/views.cljs b/src/status_im/ui/screens/wallet/request/views.cljs index cb99f2cbcb..09d3ba0105 100644 --- a/src/status_im/ui/screens/wallet/request/views.cljs +++ b/src/status_im/ui/screens/wallet/request/views.cljs @@ -2,7 +2,7 @@ (:require-macros [status-im.utils.views :as views]) (:require [re-frame.core :as re-frame] [status-im.ui.components.react :as react] - [status-im.ui.components.qr-code :as components.qr-code] + [status-im.ui.components.qr-code-viewer.views :as components.qr-code-viewer] [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.status-bar.view :as status-bar] @@ -37,7 +37,7 @@ (views/defview qr-code [amount symbol] (views/letsubs [account [:get-current-account] chain-id [:get-network-id]] - [components.qr-code/qr-code + [components.qr-code-viewer/qr-code (let [address (ethereum/normalized-address (:address account)) params {:chain-id chain-id :value amount :symbol (or symbol :ETH)}] {:value (generate-value address params)