fix #1571 Feature/profile refactoring
Second step of refactoring guidelines to fix #1571 - use fx and cofx - specs - simplify event chain
This commit is contained in:
parent
d63d411c53
commit
cb48195383
|
@ -34,12 +34,6 @@
|
|||
(defn open-drawer [] (.openDrawer @drawer-atom))
|
||||
(defn close-drawer [] (.closeDrawer @drawer-atom))
|
||||
|
||||
(defn- update-status [new-status]
|
||||
(when-not (str/blank? new-status)
|
||||
(rf/dispatch [:check-status-change new-status])
|
||||
(rf/dispatch [:account-update {:status new-status}])
|
||||
(rf/dispatch [:set-in [:profile-edit :status] new-status])))
|
||||
|
||||
(defview profile-picture []
|
||||
[account [:get-current-account]]
|
||||
[touchable-opacity {:on-press #(rf/dispatch [:navigate-to :my-profile])
|
||||
|
@ -49,27 +43,25 @@
|
|||
|
||||
(defview name-input []
|
||||
[account [:get-current-account]
|
||||
new-name [:get-in [:profile-edit :name]]]
|
||||
(let [current-name (:name account)
|
||||
public-key (:public-key account)]
|
||||
[view {:style st/name-input-wrapper}
|
||||
name-text (r/atom nil)]
|
||||
(let [previous-name (:name account)]
|
||||
[view st/name-input-wrapper
|
||||
[text-input
|
||||
{:placeholder (gfycat/generate-gfy public-key)
|
||||
:style (st/name-input-text (s/valid? ::profile.db/name (or new-name current-name)))
|
||||
:style (st/name-input-text (s/valid? ::profile.db/name @name-text))
|
||||
:font :medium
|
||||
:default-value (or new-name current-name)
|
||||
:on-change-text #(rf/dispatch [:set-in [:profile-edit :name] %])
|
||||
:on-end-editing #(do
|
||||
(rf/dispatch [:set-in [:profile-edit :name] nil])
|
||||
(when (s/valid? ::profile.db/name new-name)
|
||||
(rf/dispatch [:account-update {:name (utils/clean-text new-name)}])))}]]))
|
||||
:default-value (or @name-text previous-name)
|
||||
:on-change-text #(reset! name-text %)
|
||||
:on-end-editing #(if (s/valid? ::profile.db/name @name-text)
|
||||
(rf/dispatch [:account-update {:name (utils/clean-text @name-text)}])
|
||||
(reset! name-text previous-name))}]]))
|
||||
|
||||
(defview status-input []
|
||||
[account [:get-current-account]
|
||||
status-edit? (r/atom false)
|
||||
status-text (r/atom nil)]
|
||||
(let [status (:status account)
|
||||
placeholder (i18n/label :t/update-status)]
|
||||
(let [placeholder (i18n/label :t/update-status)
|
||||
previous-status (:status account)]
|
||||
[view st/status-container
|
||||
(if @status-edit?
|
||||
[text-input {:style st/status-input-view
|
||||
|
@ -79,21 +71,21 @@
|
|||
:max-length 140
|
||||
:accessibility-label id/drawer-status-input
|
||||
:placeholder placeholder
|
||||
:default-value status
|
||||
:on-blur #(do
|
||||
(reset! status-edit? false)
|
||||
(update-status @status-text))
|
||||
:default-value previous-status
|
||||
:on-change-text #(let [new-status (utils/clean-text %)]
|
||||
(reset! status-text new-status)
|
||||
(if (str/includes? % "\n")
|
||||
(do
|
||||
(reset! status-edit? false)
|
||||
(update-status new-status))
|
||||
(rf/dispatch [:set-in [:profile-edit :status] new-status])))}]
|
||||
[status-view/status-view {:style (st/status-view (str/blank? status))
|
||||
(when (str/includes? % "\n")
|
||||
(reset! status-edit? false)
|
||||
(rf/dispatch [:my-profile/update-status new-status])))
|
||||
:on-blur #(do (reset! status-edit? false)
|
||||
(rf/dispatch [:my-profile/update-status @status-text]))}]
|
||||
|
||||
[status-view/status-view {:style (st/status-view (str/blank? previous-status))
|
||||
:on-press #(reset! status-edit? true)
|
||||
:number-of-lines 3
|
||||
:status (if (str/blank? status) placeholder status)}])]))
|
||||
:status (if (str/blank? previous-status)
|
||||
placeholder
|
||||
previous-status)}])]))
|
||||
|
||||
(defview transaction-list-item [{:keys [to value timestamp] :as transaction}]
|
||||
[recipient [:contact-by-address to]]
|
||||
|
@ -152,7 +144,6 @@
|
|||
[touchable-highlight
|
||||
{:on-press (fn []
|
||||
(close-drawer)
|
||||
(rf/dispatch [:set-in [:profile-edit :name] nil])
|
||||
(rf/dispatch [:navigate-to :my-profile]))}
|
||||
[view [icon :options_gray]]]])
|
||||
|
||||
|
@ -161,7 +152,6 @@
|
|||
[touchable-highlight
|
||||
{:on-press (fn []
|
||||
(close-drawer)
|
||||
(rf/dispatch [:set-in [:profile-edit :name] nil])
|
||||
(rf/dispatch [:navigate-to :accounts]))}
|
||||
[view
|
||||
[text {:style st/switch-account-text
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
:current-chat-id console-chat-id
|
||||
:loading-allowed true
|
||||
:selected-participants #{}
|
||||
:profile-edit {:edit? false
|
||||
:my-profile/edit {:edit? false
|
||||
:name nil
|
||||
:email nil
|
||||
:status nil
|
||||
|
@ -97,7 +97,8 @@
|
|||
:group/contact-group-id
|
||||
:group/group-type
|
||||
:group/selected-contacts
|
||||
:group/groups-order]
|
||||
:group/groups-order
|
||||
:my-profile/edit]
|
||||
:opt-un
|
||||
[::current-public-key
|
||||
::modal
|
||||
|
@ -158,7 +159,6 @@
|
|||
:chat/raw-unviewed-messages
|
||||
:chat/bot-db
|
||||
:chat/geolocation
|
||||
:profile/profile-edit
|
||||
:transactions/transactions
|
||||
:transactions/transactions-queue
|
||||
:transactions/selected-transaction
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
(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]
|
||||
|
@ -19,10 +20,26 @@
|
|||
(or (string/blank? email)
|
||||
(and (string? email) (re-matches pattern email)))))
|
||||
|
||||
(spec/def ::name correct-name?)
|
||||
(spec/def ::email correct-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,")))
|
||||
|
||||
|
||||
(spec/def :profile/name (spec/nilable correct-name?))
|
||||
|
||||
(spec/def ::profile (spec/keys :req-un [:profile/name]))
|
||||
|
||||
|
||||
(spec/def ::name (spec/or :name correct-name?
|
||||
:empty-string string/blank?))
|
||||
(spec/def ::email (spec/nilable correct-email?))
|
||||
(spec/def ::edit? boolean?)
|
||||
(spec/def ::status (spec/nilable string?))
|
||||
(spec/def ::photo-path (spec/nilable base64-encoded-image-path?))
|
||||
(spec/def ::edit-status? boolean?)
|
||||
|
||||
(spec/def ::profile (spec/keys :req-un [::name]))
|
||||
|
||||
;; EDIT PROFILE
|
||||
(spec/def :profile/profile-edit (spec/nilable map?))
|
||||
(spec/def :my-profile/edit (allowed-keys
|
||||
:req-un [::email ::edit? ::name ::status ::photo-path]
|
||||
:opt-un [::edit-status?]))
|
||||
|
|
|
@ -24,15 +24,15 @@
|
|||
:actions [{:image :blank}]}])
|
||||
|
||||
(defview profile-name-input []
|
||||
(letsubs [new-profile-name [:get-in [:profile-edit :name]]]
|
||||
(letsubs [new-profile-name [:get-in [:my-profile/edit :name]]]
|
||||
[react/view
|
||||
[text-input-with-label {:label (label :t/name)
|
||||
:default-value new-profile-name
|
||||
:on-change-text #(dispatch [:set-in [:profile-edit :name] %])}]]))
|
||||
:on-change-text #(dispatch [:set-in [:my-profile/edit :name] %])}]]))
|
||||
|
||||
(def profile-icon-options
|
||||
[{:text (label :t/image-source-gallery)
|
||||
:value #(dispatch [:open-image-picker])}
|
||||
:value #(dispatch [:my-profile/update-picture])}
|
||||
{:text (label :t/image-source-make-photo)
|
||||
:value (fn []
|
||||
(dispatch [:request-permissions
|
||||
|
@ -43,8 +43,8 @@
|
|||
(utils/show-popup (label :t/error)
|
||||
(label :t/camera-access-error)))))]))}])
|
||||
|
||||
(defn edit-profile-bage [contact]
|
||||
[react/view styles/edit-profile-bage
|
||||
(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
|
||||
|
@ -66,12 +66,12 @@
|
|||
:max-length 140
|
||||
:placeholder (label :t/status)
|
||||
:style styles/profile-status-input
|
||||
:on-change-text #(dispatch [:set-in [:profile-edit :status] (clean-text %)])
|
||||
:on-blur #(dispatch [:set-in [:profile-edit :edit-status?] false])
|
||||
:on-change-text #(dispatch [:set-in [:my-profile/edit :status] (clean-text %)])
|
||||
:on-blur #(dispatch [:set-in [:my-profile/edit :edit-status?] false])
|
||||
:blur-on-submit true
|
||||
:on-submit-editing #(.blur @input-ref)
|
||||
:default-value status}]
|
||||
[react/touchable-highlight {:on-press #(dispatch [:set-in [:profile-edit :edit-status?] true])}
|
||||
[react/touchable-highlight {:on-press #(dispatch [:set-in [:my-profile/edit :edit-status?] true])}
|
||||
[react/view
|
||||
(if (string/blank? status)
|
||||
[react/text {:style styles/add-a-status}
|
||||
|
@ -87,8 +87,8 @@
|
|||
|
||||
(defview edit-my-profile []
|
||||
(letsubs [current-account [:get-current-account]
|
||||
changed-account [:get :profile-edit]]
|
||||
{:component-will-unmount #(dispatch [:set-in [:profile-edit :edit-status?] false])}
|
||||
changed-account [:get :my-profile/edit]]
|
||||
{:component-will-unmount #(dispatch [:set-in [:my-profile/edit :edit-status?] false])}
|
||||
(let [profile-edit-data-valid? (spec/valid? ::db/profile changed-account)
|
||||
profile-edit-data-changed? (or (not= (:name current-account) (:name changed-account))
|
||||
(not= (:status current-account) (:status changed-account))
|
||||
|
@ -97,10 +97,8 @@
|
|||
[status-bar]
|
||||
[edit-my-profile-toolbar]
|
||||
[react/view styles/edit-my-profile-form
|
||||
[edit-profile-bage changed-account]
|
||||
[edit-profile-badge changed-account]
|
||||
[edit-profile-status changed-account]
|
||||
[status-prompt changed-account]]
|
||||
(when (and profile-edit-data-changed? profile-edit-data-valid?)
|
||||
[sticky-button (label :t/save) #(do
|
||||
(dispatch [:check-status-change (:status changed-account)])
|
||||
(dispatch [:account-update changed-account]))])])))
|
||||
[sticky-button (label :t/save) #(dispatch [:my-profile/save-changes])])])))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.ui.screens.profile.events
|
||||
(:require [re-frame.core :as re-frame :refer [reg-fx]]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame :refer [reg-fx]]
|
||||
[status-im.components.react :refer [show-image-picker]]
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
[status-im.ui.screens.profile.navigation]
|
||||
|
@ -7,52 +8,71 @@
|
|||
[status-im.utils.image-processing :refer [img->base64]]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn message-user [identity]
|
||||
(when identity
|
||||
(re-frame/dispatch [:navigation-replace :chat identity])))
|
||||
|
||||
(handlers/register-handler
|
||||
(reg-fx
|
||||
:open-image-picker
|
||||
(handlers/side-effect!
|
||||
(fn [_ _]
|
||||
(show-image-picker
|
||||
(fn [image]
|
||||
(let [path (get (js->clj image) "path")
|
||||
_ (log/debug path)
|
||||
on-success (fn [base64]
|
||||
(re-frame/dispatch [:set-in [:profile-edit :photo-path] (str "data:image/jpeg;base64," base64)]))
|
||||
on-error (fn [type error]
|
||||
(.log js/console type error))]
|
||||
(img->base64 path on-success on-error)))))))
|
||||
;; the image picker is only used here for now, this effect can be use in other scenarios as well
|
||||
(fn [callback-event]
|
||||
(show-image-picker
|
||||
(fn [image]
|
||||
(let [path (get (js->clj image) "path")
|
||||
_ (log/debug path)
|
||||
on-success (fn [base64]
|
||||
(re-frame/dispatch [callback-event base64]))
|
||||
on-error (fn [type error]
|
||||
(.log js/console type error))]
|
||||
(img->base64 path on-success on-error))))))
|
||||
|
||||
(handlers/register-handler
|
||||
:phone-number-change-requested
|
||||
(handlers/register-handler-fx
|
||||
:profile/send-transaction
|
||||
(fn [_ [_ chat-id]]
|
||||
{:dispatch-n [[:clear-seq-arguments]
|
||||
[:navigate-to :chat chat-id]
|
||||
;; TODO https://github.com/status-im/status-react/issues/1621
|
||||
[:select-chat-input-command {:name "send"}]]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:profile/send-message
|
||||
(fn [_ [_ identity]]
|
||||
(when identity
|
||||
{:dispatch [:navigation-replace :chat identity]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:my-profile/edit
|
||||
(fn [{:keys [db]} [_ edit-type edit-value]]
|
||||
(let [current-account-id (:current-account-id db)
|
||||
current-account (select-keys (get-in db [:accounts current-account-id])
|
||||
[:name :photo-path :status])
|
||||
new-db (-> db
|
||||
(update-in [:my-profile/edit] merge current-account)
|
||||
(assoc-in [:my-profile/edit :edit-status?] (= edit-type :status true)))]
|
||||
{:db new-db
|
||||
:dispatch [:navigate-to :edit-my-profile]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:my-profile/update-status
|
||||
(fn [_ [_ new-status]]
|
||||
(when-not (string/blank? new-status)
|
||||
{:dispatch-n [[:check-status-change new-status]
|
||||
[:account-update {:status new-status}]]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:my-profile/update-phone-number
|
||||
;; Switch user to the console issuing the !phone command automatically to let him change his phone number.
|
||||
;; We allow to change phone number only from console because this requires entering SMS verification code.
|
||||
(handlers/side-effect!
|
||||
(fn [db _]
|
||||
(re-frame/dispatch [:navigate-to :chat console-chat-id])
|
||||
(js/setTimeout #(re-frame/dispatch [:select-chat-input-command {:name "phone"}]) 500))))
|
||||
(fn [_ _]
|
||||
{:dispatch-n [[:navigate-to :chat console-chat-id]
|
||||
[:select-chat-input-command {:name "phone"}]]}))
|
||||
|
||||
(handlers/register-handler
|
||||
:open-chat-with-the-send-transaction
|
||||
(handlers/side-effect!
|
||||
(fn [db [_ chat-id]]
|
||||
(re-frame/dispatch [:clear-seq-arguments])
|
||||
(re-frame/dispatch [:navigate-to :chat chat-id])
|
||||
(js/setTimeout #(re-frame/dispatch [:select-chat-input-command {:name "send"}]) 500))))
|
||||
(handlers/register-handler-fx
|
||||
:my-profile/update-picture
|
||||
(fn [{:keys [db]} [this-event base64-image]]
|
||||
(if base64-image
|
||||
{:db (assoc-in db [:my-profile/edit :photo-path] (str "data:image/jpeg;base64," base64-image))}
|
||||
{:open-image-picker this-event})))
|
||||
|
||||
(defn prepare-edit-profile
|
||||
[{:keys [current-account-id] :as db} _]
|
||||
(let [current-account (select-keys (get-in db [:accounts current-account-id])
|
||||
[:name :photo-path :status])]
|
||||
(update-in db [:profile-edit] merge current-account)))
|
||||
|
||||
(defn open-edit-profile [_ _]
|
||||
(re-frame/dispatch [:navigate-to :edit-my-profile]))
|
||||
|
||||
(handlers/register-handler
|
||||
:open-edit-my-profile
|
||||
(handlers/handlers->
|
||||
prepare-edit-profile
|
||||
open-edit-profile))
|
||||
(handlers/register-handler-fx
|
||||
:my-profile/save-changes
|
||||
(fn [{:keys [db]} _]
|
||||
(let [{:keys [:my-profile/edit]} db]
|
||||
{:dispatch-n [[:check-status-change (:status edit)]
|
||||
[:account-update edit]]})))
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
_ (log/debug "Captured image: " path)
|
||||
on-success (fn [base64]
|
||||
(log/debug "Captured success: " base64)
|
||||
(dispatch [:set-in [:profile-edit :photo-path] (str "data:image/jpeg;base64," base64)])
|
||||
(dispatch [:set-in [:my-profile/edit :photo-path] (str "data:image/jpeg;base64," base64)])
|
||||
(dispatch [:navigate-back]))
|
||||
on-error (fn [type error]
|
||||
(log/debug type error))]
|
||||
|
|
|
@ -50,10 +50,10 @@
|
|||
:padding 16
|
||||
:max-height 114})
|
||||
|
||||
(def profile-bage
|
||||
(def profile-badge
|
||||
{:flex-direction :row})
|
||||
|
||||
(def edit-profile-bage
|
||||
(def edit-profile-badge
|
||||
{:flex-direction :row
|
||||
:padding-left 24})
|
||||
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
[status-im.components.toolbar-new.actions :as actions]
|
||||
[status-im.components.toolbar-new.view :refer [toolbar]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.ui.screens.profile.events :as profile.event :refer [message-user]]
|
||||
[status-im.ui.screens.profile.styles :as styles]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.utils :refer [hash-tag?]])
|
||||
(:require-macros [status-im.utils.views :refer [defview]]))
|
||||
|
||||
(defn my-profile-toolbar []
|
||||
[toolbar {:actions [(actions/opts [{:value #(dispatch [:open-edit-my-profile])
|
||||
[toolbar {:actions [(actions/opts [{:value #(dispatch [:my-profile/edit])
|
||||
:text (label :t/edit)}])]}])
|
||||
|
||||
(defn profile-toolbar [contact]
|
||||
|
@ -43,7 +42,7 @@
|
|||
(label :t/active-unknown))))
|
||||
|
||||
(defn profile-badge [{:keys [name last-online] :as contact}]
|
||||
[react/view styles/profile-bage
|
||||
[react/view styles/profile-badge
|
||||
[my-profile-icon {:account contact
|
||||
:edit? false}]
|
||||
[react/view styles/profile-badge-name-container
|
||||
|
@ -66,13 +65,13 @@
|
|||
[action-separator]
|
||||
[action-button (label :t/start-conversation)
|
||||
:chats_blue
|
||||
#(message-user whisper-identity)]
|
||||
#(dispatch [:profile/send-message whisper-identity])]
|
||||
(when-not dapp?
|
||||
[react/view
|
||||
[action-separator]
|
||||
[action-button (label :t/send-transaction)
|
||||
:arrow_right_blue
|
||||
#(dispatch [:open-chat-with-the-send-transaction chat-id])]])])
|
||||
#(dispatch [:profile/send-transaction chat-id])]])])
|
||||
|
||||
(defn profile-info-item [{:keys [label value options text-mode empty-value?]}]
|
||||
[react/view styles/profile-setting-item
|
||||
|
@ -160,22 +159,18 @@
|
|||
[info-item-separator]
|
||||
[profile-info-phone-item
|
||||
phone
|
||||
[{:value #(dispatch [:phone-number-change-requested])
|
||||
[{:value #(dispatch [:my-profile/change-phone-number])
|
||||
:text (label :t/edit)}]]])
|
||||
|
||||
(defn- profile-status-on-press []
|
||||
(dispatch [:set-in [:profile-edit :edit-status?] true])
|
||||
(dispatch [:open-edit-my-profile]))
|
||||
|
||||
(defn profile-status [status & [edit?]]
|
||||
[react/view styles/profile-status-container
|
||||
(if (or (nil? status) (string/blank? status))
|
||||
[react/touchable-highlight {:on-press profile-status-on-press}
|
||||
[react/touchable-highlight {:on-press #(dispatch [:my-profile/edit :status])}
|
||||
[react/view
|
||||
[react/text {:style styles/add-a-status}
|
||||
(label :t/add-a-status)]]]
|
||||
[react/scroll-view
|
||||
[react/touchable-highlight {:on-press (when edit? profile-status-on-press)}
|
||||
[react/touchable-highlight {:on-press (when edit? #(dispatch [:my-profile/edit :status]))}
|
||||
[react/view
|
||||
[react/text {:style styles/profile-status-text}
|
||||
(colorize-status-hashtags status)]]]])])
|
||||
|
|
Loading…
Reference in New Issue