diff --git a/src/status_im/components/drawer/view.cljs b/src/status_im/components/drawer/view.cljs index e0c65c145e..f65dd56cd9 100644 --- a/src/status_im/components/drawer/view.cljs +++ b/src/status_im/components/drawer/view.cljs @@ -1,5 +1,5 @@ (ns status-im.components.drawer.view - (:require-macros [status-im.utils.views :refer [defview]]) + (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [cljs.spec.alpha :as s] [clojure.string :as str] [reagent.core :as r] @@ -30,64 +30,73 @@ [status-im.utils.money :as money])) (defonce drawer-atom (atom nil)) -(defn open-drawer [] (.openDrawer @drawer-atom)) -(defn close-drawer [] (.closeDrawer @drawer-atom)) +(defn open-drawer! [] (.openDrawer @drawer-atom)) +(defn close-drawer! [] (.closeDrawer @drawer-atom)) + +;; the save-event subscription is here because no save action would +;; be dispatched when the user presses a screen changing zone while +;; editing the name or status field + +(defn save-profile! [] + (when-let [save-event @(rf/subscribe [:my-profile.drawer/save-event])] + (rf/dispatch [save-event]))) + +(defn navigate-to-profile [] + (close-drawer!) + (save-profile!) + (rf/dispatch [:navigate-to :my-profile])) + +(defn navigate-to-accounts [] + (close-drawer!) + (save-profile!) + (rf/dispatch [:navigate-to :accounts])) (defview profile-picture [] - [account [:get-current-account]] - [touchable-opacity {:on-press #(rf/dispatch [:navigate-to :my-profile]) - :style st/user-photo-container} - [view - [ci/chat-icon (:photo-path account) {:size 52 - :accessibility-label :drawer-profile-icon}]]]) + (letsubs [account [:get-current-account]] + [touchable-opacity {:on-press navigate-to-profile + :style st/user-photo-container} + [view + [ci/chat-icon (:photo-path account) {:size 52 + :accessibility-label :drawer-profile-icon}]]])) (defview name-input [] - [account [:get-current-account] - name-text (r/atom nil)] - (let [previous-name (:name account) - public-key (:public-key account) - placeholder (gfycat/generate-gfy public-key)] + (letsubs [profile-name [:my-profile.drawer/get :name] + valid-name? [:my-profile.drawer/valid-name?] + placeholder [:get :my-profile/default-name]] [view st/name-input-wrapper [text-input {:placeholder placeholder - :style (st/name-input-text (s/valid? ::profile.db/name @name-text)) + :style (st/name-input-text valid-name?) :font :medium - :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 (or @name-text placeholder))}]) - (reset! name-text previous-name))}]])) + :default-value profile-name + :on-focus #(rf/dispatch [:my-profile.drawer/edit-name]) + :on-change-text #(rf/dispatch [:my-profile.drawer/update-name %]) + :on-end-editing #(rf/dispatch [:my-profile.drawer/save-name])}]])) (defview status-input [] - [account [:get-current-account] - status-edit? (r/atom false) - status-text (r/atom nil)] - (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 - :multiline true - :auto-focus true - :focus @status-edit? - :max-length 140 - :accessibility-label :drawer-status-input - :placeholder placeholder - :default-value previous-status - :on-change-text #(let [new-status (utils/clean-text %)] - (reset! status-text new-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]))}] + (letsubs [edit-status? [:my-profile.drawer/get :edit-status?] + status [:my-profile.drawer/get :status]] + (let [placeholder (i18n/label :t/update-status)] + [view st/status-container + (if edit-status? + [text-input {:style st/status-input-view + :multiline true + :auto-focus true + :focus edit-status? + :max-length 140 + :accessibility-label :drawer-status-input + :placeholder placeholder + :default-value status + :on-change-text #(rf/dispatch [:my-profile.drawer/update-status %]) + :on-end-editing #(when edit-status? + (rf/dispatch [:my-profile.drawer/save-status]))}] - [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? previous-status) - placeholder - previous-status)}])])) + [status-view/status-view {:style (st/status-view (str/blank? status)) + :number-of-lines 3 + :status (if (str/blank? status) + placeholder + status) + :on-press #(rf/dispatch [:my-profile.drawer/edit-status])}])]))) (defview transaction-list-item [{:keys [to value timestamp] :as transaction}] [recipient [:contact-by-address to]] @@ -144,17 +153,13 @@ (defn options-btn [] [view {:style st/options-button} [touchable-highlight - {:on-press (fn [] - (close-drawer) - (rf/dispatch [:navigate-to :my-profile]))} + {:on-press navigate-to-profile} [view [vi/icon :icons/options]]]]) (defn switch-account [] [view st/switch-account-container [touchable-highlight - {:on-press (fn [] - (close-drawer) - (rf/dispatch [:navigate-to :accounts]))} + {:on-press navigate-to-accounts} [view [text {:style st/switch-account-text :font (if platform/android? :medium :default) diff --git a/src/status_im/ui/screens/chats_list/views.cljs b/src/status_im/ui/screens/chats_list/views.cljs index 8d05873357..e4c8228346 100644 --- a/src/status_im/ui/screens/chats_list/views.cljs +++ b/src/status_im/ui/screens/chats_list/views.cljs @@ -5,7 +5,7 @@ [status-im.components.renderers.renderers :as renderers] [status-im.components.react :as react] [status-im.components.native-action-button :refer [native-action-button]] - [status-im.components.drawer.view :refer [open-drawer]] + [status-im.components.drawer.view :as drawer] [status-im.components.styles :refer [color-blue]] [status-im.components.status-bar :refer [status-bar]] [status-im.components.toolbar-new.view :as toolbar] @@ -39,7 +39,7 @@ (defn toolbar-view [] [toolbar/toolbar2 {} - [toolbar/nav-button (act/hamburger open-drawer)] + [toolbar/nav-button (act/hamburger open-drawer!)] [toolbar/content-title (i18n/label :t/chats)] [toolbar/actions (if ios? diff --git a/src/status_im/ui/screens/contacts/views.cljs b/src/status_im/ui/screens/contacts/views.cljs index 4839a6f521..7d9a17c009 100644 --- a/src/status_im/ui/screens/contacts/views.cljs +++ b/src/status_im/ui/screens/contacts/views.cljs @@ -8,7 +8,7 @@ native-action-button-item]] [status-im.components.toolbar-new.view :as toolbar] [status-im.components.toolbar-new.actions :as act] - [status-im.components.drawer.view :refer [open-drawer]] + [status-im.components.drawer.view :as drawer] [status-im.components.icons.custom-icons :refer [ion-icon]] [status-im.components.contact.contact :refer [contact-view]] [status-im.utils.platform :refer [platform-specific ios? android?]] @@ -32,7 +32,7 @@ (defn toolbar-view [] [toolbar/toolbar2 {} - [toolbar/nav-button (act/hamburger open-drawer)] + [toolbar/nav-button (act/hamburger open-drawer!)] [toolbar/content-title (label :t/contacts)] [toolbar/actions (toolbar-actions)]]) @@ -44,9 +44,9 @@ (defn contact-options [{:keys [unremovable?] :as contact} group] (let [delete-contact-opt {:value #(u/show-confirmation - (str (label :t/delete-contact) "?") (label :t/delete-contact-confirmation) - (label :t/delete) - (fn [] (dispatch [:hide-contact contact]))) + (str (label :t/delete-contact) "?") (label :t/delete-contact-confirmation) + (label :t/delete) + (fn [] (dispatch [:hide-contact contact]))) :text (label :t/delete-contact) :destructive? true} options (if unremovable? [] [delete-contact-opt])] @@ -70,17 +70,17 @@ [view st/contacts-list [common/list-footer] (doall - (map (fn [contact] - ^{:key contact} - [view - [contact-view - {:contact contact - :extended? edit? - :on-press #(dispatch [:open-chat-with-contact %]) - :extend-options (contact-options contact group)}] - (when-not (= contact (last contacts)) - [common/list-separator])]) - contacts))] + (map (fn [contact] + ^{:key contact} + [view + [contact-view + {:contact contact + :extended? edit? + :on-press #(dispatch [:open-chat-with-contact %]) + :extend-options (contact-options contact group)}] + (when-not (= contact (last contacts)) + [common/list-separator])]) + contacts))] (when (< contacts-limit contacts-count) [view [common/list-separator] diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index c4f940ae7b..998cd1c9a3 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -27,11 +27,6 @@ :current-chat-id console-chat-id :loading-allowed true :selected-participants #{} - :my-profile/edit {:edit? false - :name nil - :email nil - :status nil - :photo-path nil} :discoveries {} :discover-search-tags '() :tags [] @@ -105,7 +100,9 @@ :accounts/current-account-id :accounts/recover :accounts/login - :my-profile/edit] + :my-profile/drawer + :my-profile/profile + :my-profile/default-name] :opt-un [::current-public-key ::modal diff --git a/src/status_im/ui/screens/discover/views.cljs b/src/status_im/ui/screens/discover/views.cljs index dad42d7f94..feedd6315b 100644 --- a/src/status_im/ui/screens/discover/views.cljs +++ b/src/status_im/ui/screens/discover/views.cljs @@ -1,23 +1,23 @@ (ns status-im.ui.screens.discover.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require - [re-frame.core :refer [dispatch subscribe]] - [clojure.string :as str] - [status-im.components.react :refer [view - scroll-view - text - text-input]] - [status-im.components.icons.vector-icons :as vi] - [status-im.components.toolbar-new.view :refer [toolbar-with-search]] - [status-im.components.toolbar-new.actions :as act] - [status-im.components.drawer.view :refer [open-drawer]] - [status-im.components.carousel.carousel :refer [carousel]] - [status-im.ui.screens.discover.views.popular-list :refer [discover-popular-list]] - [status-im.ui.screens.discover.views.discover-list-item :refer [discover-list-item]] - [status-im.utils.platform :refer [platform-specific]] - [status-im.i18n :refer [label]] - [status-im.ui.screens.discover.styles :as st] - [status-im.ui.screens.contacts.styles :as contacts-st])) + [re-frame.core :refer [dispatch subscribe]] + [clojure.string :as str] + [status-im.components.react :refer [view + scroll-view + text + text-input]] + [status-im.components.icons.vector-icons :as vi] + [status-im.components.toolbar-new.view :refer [toolbar-with-search]] + [status-im.components.toolbar-new.actions :as act] + [status-im.components.drawer.view :as drawer] + [status-im.components.carousel.carousel :refer [carousel]] + [status-im.ui.screens.discover.views.popular-list :refer [discover-popular-list]] + [status-im.ui.screens.discover.views.discover-list-item :refer [discover-list-item]] + [status-im.utils.platform :refer [platform-specific]] + [status-im.i18n :refer [label]] + [status-im.ui.screens.discover.styles :as st] + [status-im.ui.screens.contacts.styles :as contacts-st])) (defn get-hashtags [status] (let [hashtags (map #(str/lower-case (str/replace % #"#" "")) (re-seq #"[^ !?,;:.]+" status))] @@ -30,7 +30,7 @@ :search-key :discover :title (label :t/discover) :search-placeholder (label :t/search-tags) - :nav-action (act/hamburger open-drawer) + :nav-action (act/hamburger drawer/open-drawer!) :on-search-submit (fn [text] (when-not (str/blank? text) (let [hashtags (get-hashtags text)] diff --git a/src/status_im/ui/screens/profile/db.cljs b/src/status_im/ui/screens/profile/db.cljs index 3aea00d958..5855006306 100644 --- a/src/status_im/ui/screens/profile/db.cljs +++ b/src/status_im/ui/screens/profile/db.cljs @@ -6,6 +6,8 @@ [status-im.constants :as constants] [status-im.utils.homoglyph :as homoglyph])) +(def account-profile-keys [:name :photo-path :status]) + (defn correct-name? [username] (when-let [username (some-> username (string/trim))] (every? false? @@ -24,22 +26,13 @@ (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/name correct-name?) +(spec/def :profile/status (spec/nilable string?)) +(spec/def :profile/photo-path (spec/nilable base64-encoded-image-path?)) ;; EDIT PROFILE -(spec/def :my-profile/edit (allowed-keys - :req-un [::email ::edit? ::name ::status ::photo-path] - :opt-un [::edit-status?])) +(spec/def :my-profile/default-name string?) +(spec/def :my-profile/profile (spec/keys :opt-un [::name :profile/status :profile/photo-path + ::edit-status? ::valid-name?])) +(spec/def :my-profile/drawer (spec/keys :opt-un [::name :profile/status + ::edit-status? ::valid-name?])) diff --git a/src/status_im/ui/screens/profile/edit/views.cljs b/src/status_im/ui/screens/profile/edit/views.cljs index 627a61ee5b..5b666282a0 100644 --- a/src/status_im/ui/screens/profile/edit/views.cljs +++ b/src/status_im/ui/screens/profile/edit/views.cljs @@ -24,11 +24,15 @@ :actions [{:image :blank}]}]) (defview profile-name-input [] - (letsubs [new-profile-name [:get-in [:my-profile/edit :name]]] + (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 new-profile-name - :on-change-text #(dispatch [:set-in [:my-profile/edit :name] %])}]])) + [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) @@ -39,9 +43,10 @@ [: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)))))]))}]) + #(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 @@ -54,24 +59,21 @@ [react/view styles/edit-profile-name-container [profile-name-input]]]) -(defn edit-profile-status [{:keys [status edit-status?]}] - (let [input-ref (reagent/atom nil)] +(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 - {:ref #(reset! input-ref %) - :auto-focus edit-status? + {: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 [: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) + :on-change-text #(dispatch [:my-profile/update-status %]) :default-value status}] - [react/touchable-highlight {:on-press #(dispatch [:set-in [:my-profile/edit :edit-status?] true])} + [react/touchable-highlight {:on-press #(dispatch [:my-profile/edit-profile :status])} [react/view (if (string/blank? status) [react/text {:style styles/add-a-status} @@ -86,19 +88,16 @@ (colorize-status-hashtags (label :t/status-prompt))]])) (defview edit-my-profile [] - (letsubs [current-account [:get-current-account] - 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)) - (not= (:photo-path current-account) (:photo-path changed-account)))] - [react/keyboard-avoiding-view {:style styles/profile} - [status-bar] - [edit-my-profile-toolbar] - [react/view styles/edit-my-profile-form - [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) #(dispatch [:my-profile/save-changes])])]))) + (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/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 3b16713317..6b1d286207 100644 --- a/src/status_im/ui/screens/profile/events.cljs +++ b/src/status_im/ui/screens/profile/events.cljs @@ -1,15 +1,17 @@ (ns status-im.ui.screens.profile.events - (:require [clojure.string :as string] + (:require [clojure.spec.alpha :as spec] + [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.db :as db] [status-im.ui.screens.profile.navigation] + [status-im.utils.gfycat.core :as gfycat] [status-im.utils.handlers :as handlers] [status-im.utils.image-processing :refer [img->base64]] + [status-im.utils.utils :as utils] [taoensso.timbre :as log])) -(def account-profile-keys [:name :photo-path :status]) - (reg-fx :open-image-picker ;; the image picker is only used here for now, this effect can be use in other scenarios as well @@ -38,26 +40,6 @@ (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 (:accounts/current-account-id db) - current-account (-> db - (get-in [:accounts/accounts current-account-id]) - (select-keys account-profile-keys)) - 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. @@ -66,16 +48,119 @@ {:dispatch-n [[:navigate-to :chat console-chat-id] [:select-chat-input-command {:name "phone"}]]})) +(defn get-current-account [{:keys [:accounts/current-account-id] :as db}] + (get-in db [:accounts/accounts current-account-id])) + +(handlers/register-handler-fx + :my-profile.drawer/edit-name + (fn [{:keys [db]} _] + (let [{:my-profile/keys [default-name edit auto-save]} db + {:keys [name public-key]} (get-current-account db)] + {:db (cond-> db + (not default-name) (assoc :my-profile/default-name (gfycat/generate-gfy public-key)) + :always (assoc-in [:my-profile/drawer :name] name))}))) + +(handlers/register-handler-fx + :my-profile.drawer/edit-status + (fn [{:keys [db]} _] + (let [{:keys [status]} (get-current-account db)] + {:db (-> db + (assoc-in [:my-profile/drawer :status] status) + (assoc-in [:my-profile/drawer :edit-status?] true))}))) + +(handlers/register-handler-fx + :my-profile/edit-profile + (fn [{:keys [db]} [_ edit-status?]] + (let [new-db (-> db + (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]}))) + +(defn valid-name? [name] + (spec/valid? :profile/name name)) + +(handlers/register-handler-fx + :my-profile.drawer/update-name + (fn [{:keys [db]} [_ name]] + {:db (-> db + (assoc-in [:my-profile/drawer :valid-name?] (valid-name? name)) + (assoc-in [:my-profile/drawer :name] name))})) + +(handlers/register-handler-fx + :my-profile.drawer/update-status + (fn [{:keys [db]} [_ status]] + (let [linebreak? (string/includes? status "\n") + new-db (if linebreak? + (-> db + (assoc-in [:my-profile/drawer :edit-status?] nil) + (assoc-in [:my-profile/drawer :status] (utils/clean-text status))) + (assoc-in db [:my-profile/drawer :status] status))] + (if linebreak? + {:db new-db + :dispatch [:my-profile.drawer/save-status]} + {:db new-db})))) + +(handlers/register-handler-fx + :my-profile/update-name + (fn [{:keys [db]} [_ name]] + {:db (-> db + (assoc-in [:my-profile/profile :valid-name?] (valid-name? name)) + (assoc-in [:my-profile/profile :name] name))})) + +(handlers/register-handler-fx + :my-profile/update-status + (fn [{:keys [db]} [_ status]] + {:db (if (string/includes? status "\n") + (-> db + (assoc-in [:my-profile/profile :edit-status?] nil) + (assoc-in [:my-profile/profile :status] (utils/clean-text status))) + (assoc-in db [:my-profile/profile :status] status))})) + (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))} + {:db (assoc-in db [:my-profile/profile :photo-path] (str "data:image/jpeg;base64," base64-image))} {:open-image-picker this-event}))) +(defn clean-name [{:accounts/keys [current-account-id] :as db} edit-view] + (let [name (get-in db [edit-view :name])] + (if (valid-name? name) + name + (get-in db [:accounts/accounts current-account-id :name])))) + +(defn clear-profile [db] + (dissoc db :my-profile/profile :my-profile/drawer :my-profile/default-name)) + (handlers/register-handler-fx - :my-profile/save-changes + :my-profile.drawer/save-name (fn [{:keys [db]} _] - (let [{:keys [:my-profile/edit]} db] - {:dispatch-n [[:check-status-change (:status edit)] - [:account-update (select-keys edit account-profile-keys)]]}))) + (let [cleaned-name (clean-name db :my-profile/drawer)] + {:db (clear-profile db) + :dispatch [:account-update {:name cleaned-name}]}))) + +(handlers/register-handler-fx + :my-profile.drawer/save-status + (fn [{:keys [db]} _] + (let [status (get-in db [:my-profile/drawer :status]) + new-db (clear-profile db)] + (if (string/blank? status) + {:db new-db} + {:db new-db + :dispatch-n [[:check-status-change status] + [:account-update {:status status}]]})))) + +(handlers/register-handler-fx + :my-profile/save-profile + (fn [{:keys [db]} _] + (let [{: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}] + {:db (clear-profile db) + :dispatch-n [[:check-status-change status] + [:account-update cleaned-edit] + [:navigate-back]]}))) diff --git a/src/status_im/ui/screens/profile/photo_capture/views.cljs b/src/status_im/ui/screens/profile/photo_capture/views.cljs index b44b0dc580..99236df4ab 100644 --- a/src/status_im/ui/screens/profile/photo_capture/views.cljs +++ b/src/status_im/ui/screens/profile/photo_capture/views.cljs @@ -18,7 +18,7 @@ _ (log/debug "Captured image: " path) on-success (fn [base64] (log/debug "Captured success: " base64) - (dispatch [:set-in [:my-profile/edit :photo-path] (str "data:image/jpeg;base64," base64)]) + (dispatch [:my-profile/update-picture base64]) (dispatch [:navigate-back])) on-error (fn [type error] (log/debug type error))] diff --git a/src/status_im/ui/screens/profile/subs.cljs b/src/status_im/ui/screens/profile/subs.cljs new file mode 100644 index 0000000000..8e7f5f21ac --- /dev/null +++ b/src/status_im/ui/screens/profile/subs.cljs @@ -0,0 +1,51 @@ +(ns status-im.ui.screens.profile.subs + (:require [re-frame.core :refer [reg-sub subscribe]] + [clojure.string :as string] + [status-im.ui.screens.profile.db :refer [account-profile-keys]])) + +(defn get-in-profile [profile current-account k] + (or (get profile k) + (get current-account k))) + +(reg-sub :my-profile/get + :<- [:get-current-account] + :<- [:get :my-profile/profile] + (fn [[current-account profile] [_ k]] + (get-in-profile profile current-account k))) + +(reg-sub :my-profile.drawer/get + :<- [:get-current-account] + :<- [:get :my-profile/drawer] + (fn [[current-account profile] [_ k]] + (get-in-profile profile current-account k))) + +(reg-sub :my-profile/valid-name? + :<- [:get :my-profile/profile] + (fn [profile] + (get profile :valid-name? true))) + +(reg-sub :my-profile.drawer/valid-name? + :<- [:get :my-profile/drawer] + (fn [profile] + (or (string/blank? (:name profile)) + (get profile :valid-name? true)))) + +(reg-sub :my-profile/changed? + :<- [:get-current-account] + :<- [:get :my-profile/profile] + (fn [[current-account profile]] + (not= (select-keys current-account account-profile-keys) + (select-keys profile account-profile-keys)))) + +(reg-sub :my-profile.drawer/save-event + :<- [:get-current-account] + :<- [:get :my-profile/drawer] + (fn [[{:keys [name status]} {new-name :name new-status :status}]] + (cond + (and new-name + (not= name new-name)) + :my-profile.drawer/save-name + + (and status + (not= status new-status)) + :my-profile.drawer/save-status))) diff --git a/src/status_im/ui/screens/profile/views.cljs b/src/status_im/ui/screens/profile/views.cljs index 93ebd7d94b..5ff903807b 100644 --- a/src/status_im/ui/screens/profile/views.cljs +++ b/src/status_im/ui/screens/profile/views.cljs @@ -24,8 +24,8 @@ (:require-macros [status-im.utils.views :refer [defview]])) (defn my-profile-toolbar [] - [toolbar/toolbar {:actions [(actions/opts [{:value #(dispatch [:my-profile/edit]) - :text (label :t/edit)}])]}]) + [toolbar/toolbar {:actions [(actions/opts [{:value #(dispatch [:my-profile/edit-profile]) + :text (label :t/edit)}])]}]) (defn profile-toolbar [contact] [toolbar/toolbar @@ -172,12 +172,12 @@ (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 :status])} + [react/touchable-highlight {:on-press #(dispatch [:my-profile/edit-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? #(dispatch [:my-profile/edit :status]))} + [react/touchable-highlight {:on-press (when edit? #(dispatch [:my-profile/edit-profile :edit-status]))} [react/view [react/text {:style styles/profile-status-text} (colorize-status-hashtags status)]]]])]) diff --git a/src/status_im/ui/screens/subs.cljs b/src/status_im/ui/screens/subs.cljs index 5c63e08519..9541160fc7 100644 --- a/src/status_im/ui/screens/subs.cljs +++ b/src/status_im/ui/screens/subs.cljs @@ -7,6 +7,7 @@ status-im.ui.screens.discover.subs status-im.ui.screens.contacts.subs status-im.ui.screens.group.subs + status-im.ui.screens.profile.subs status-im.ui.screens.wallet.subs status-im.transactions.subs status-im.bots.subs)) @@ -39,4 +40,4 @@ (fn [[search-mode? chats-edit-mode? contacts-edit-mode? view-id]] (or search-mode? (and (= view-id :chat-list) chats-edit-mode?) - (and (= view-id :contact-list) contacts-edit-mode?)))) \ No newline at end of file + (and (= view-id :contact-list) contacts-edit-mode?)))) diff --git a/src/status_im/ui/screens/wallet/main/views.cljs b/src/status_im/ui/screens/wallet/main/views.cljs index 9ba8e7a93a..4db6e66f70 100644 --- a/src/status_im/ui/screens/wallet/main/views.cljs +++ b/src/status_im/ui/screens/wallet/main/views.cljs @@ -42,7 +42,7 @@ (defn toolbar-view [] [toolbar/toolbar2 {:style wallet-styles/toolbar} - [toolbar/nav-button (act/hamburger-white drawer/open-drawer)] + [toolbar/nav-button (act/hamburger-white drawer/open-drawer!)] [toolbar-title] [toolbar/actions [(assoc (act/opts [{:text (i18n/label :t/wallet-settings) :value show-not-implemented!}]) :icon-opts {:color :white}) diff --git a/test/cljs/status_im/test/profile/events.cljs b/test/cljs/status_im/test/profile/events.cljs index 5dbf8bc352..fb5e07aae6 100644 --- a/test/cljs/status_im/test/profile/events.cljs +++ b/test/cljs/status_im/test/profile/events.cljs @@ -29,26 +29,28 @@ (run-test-sync (test-fixtures) (let [accounts (rf/subscribe [:get-accounts]) - address (:address new-account) - new-status "It's a new status!"] + address (:address new-account)] (rf/dispatch [:initialize-db]) (rf/dispatch [:add-account new-account]) (rf/dispatch [:set-current-account address]) - (testing "Setting status" - (is (= (:status new-account) (-> @accounts - (get address) - :status))) - (rf/dispatch [:my-profile/update-status new-status]) - (is (= new-status (-> @accounts - (get address) - :status)))) - (testing "Setting phone number" - (is (nil? (-> @accounts - (get address) - :phone))) - (rf/dispatch [:set-in [:my-profile/edit :edit-status?] true]) - (rf/dispatch [:set-in [:my-profile/edit :name] "It's my new name"]) - (rf/dispatch [:my-profile/save-changes]) - (is (= "It's my new name" (-> @accounts - (get address) - :name))))))) + + (testing "Setting status from edit profile screen" + (let [new-status "New edit profile status"] + (is (= (:status new-account) (-> @accounts + (get address) + :status))) + (rf/dispatch [:my-profile/edit-profile :edit-status]) + (rf/dispatch [:my-profile/update-status new-status]) + (rf/dispatch [:my-profile/save-profile]) + (is (= new-status (-> @accounts + (get address) + :status))))) + + (testing "Setting status from drawer" + (let [new-status "New drawer status"] + (rf/dispatch [:my-profile.drawer/edit-status]) + (rf/dispatch [:my-profile.drawer/update-status new-status]) + (rf/dispatch [:my-profile.drawer/save-status]) + (is (= new-status (-> @accounts + (get address) + :status))))))))