moving drawer local state to db and fixing bug

This commit is contained in:
Eric Dvorsak 2017-09-01 20:44:22 +02:00 committed by Roman Volosovskyi
parent d5981c65a1
commit ab98de0be5
14 changed files with 333 additions and 200 deletions

View File

@ -1,5 +1,5 @@
(ns status-im.components.drawer.view (ns status-im.components.drawer.view
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [cljs.spec.alpha :as s] (:require [cljs.spec.alpha :as s]
[clojure.string :as str] [clojure.string :as str]
[reagent.core :as r] [reagent.core :as r]
@ -30,64 +30,73 @@
[status-im.utils.money :as money])) [status-im.utils.money :as money]))
(defonce drawer-atom (atom nil)) (defonce drawer-atom (atom nil))
(defn open-drawer [] (.openDrawer @drawer-atom)) (defn open-drawer! [] (.openDrawer @drawer-atom))
(defn close-drawer [] (.closeDrawer @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 [] (defview profile-picture []
[account [:get-current-account]] (letsubs [account [:get-current-account]]
[touchable-opacity {:on-press #(rf/dispatch [:navigate-to :my-profile]) [touchable-opacity {:on-press navigate-to-profile
:style st/user-photo-container} :style st/user-photo-container}
[view [view
[ci/chat-icon (:photo-path account) {:size 52 [ci/chat-icon (:photo-path account) {:size 52
:accessibility-label :drawer-profile-icon}]]]) :accessibility-label :drawer-profile-icon}]]]))
(defview name-input [] (defview name-input []
[account [:get-current-account] (letsubs [profile-name [:my-profile.drawer/get :name]
name-text (r/atom nil)] valid-name? [:my-profile.drawer/valid-name?]
(let [previous-name (:name account) placeholder [:get :my-profile/default-name]]
public-key (:public-key account)
placeholder (gfycat/generate-gfy public-key)]
[view st/name-input-wrapper [view st/name-input-wrapper
[text-input [text-input
{:placeholder placeholder {:placeholder placeholder
:style (st/name-input-text (s/valid? ::profile.db/name @name-text)) :style (st/name-input-text valid-name?)
:font :medium :font :medium
:default-value (or @name-text previous-name) :default-value profile-name
:on-change-text #(reset! name-text %) :on-focus #(rf/dispatch [:my-profile.drawer/edit-name])
:on-end-editing #(if (s/valid? ::profile.db/name @name-text) :on-change-text #(rf/dispatch [:my-profile.drawer/update-name %])
(rf/dispatch [:account-update {:name (utils/clean-text (or @name-text placeholder))}]) :on-end-editing #(rf/dispatch [:my-profile.drawer/save-name])}]]))
(reset! name-text previous-name))}]]))
(defview status-input [] (defview status-input []
[account [:get-current-account] (letsubs [edit-status? [:my-profile.drawer/get :edit-status?]
status-edit? (r/atom false) status [:my-profile.drawer/get :status]]
status-text (r/atom nil)] (let [placeholder (i18n/label :t/update-status)]
(let [placeholder (i18n/label :t/update-status) [view st/status-container
previous-status (:status account)] (if edit-status?
[view st/status-container [text-input {:style st/status-input-view
(if @status-edit? :multiline true
[text-input {:style st/status-input-view :auto-focus true
:multiline true :focus edit-status?
:auto-focus true :max-length 140
:focus @status-edit? :accessibility-label :drawer-status-input
:max-length 140 :placeholder placeholder
:accessibility-label :drawer-status-input :default-value status
:placeholder placeholder :on-change-text #(rf/dispatch [:my-profile.drawer/update-status %])
:default-value previous-status :on-end-editing #(when edit-status?
:on-change-text #(let [new-status (utils/clean-text %)] (rf/dispatch [:my-profile.drawer/save-status]))}]
(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]))}]
[status-view/status-view {:style (st/status-view (str/blank? previous-status)) [status-view/status-view {:style (st/status-view (str/blank? status))
:on-press #(reset! status-edit? true) :number-of-lines 3
:number-of-lines 3 :status (if (str/blank? status)
:status (if (str/blank? previous-status) placeholder
placeholder status)
previous-status)}])])) :on-press #(rf/dispatch [:my-profile.drawer/edit-status])}])])))
(defview transaction-list-item [{:keys [to value timestamp] :as transaction}] (defview transaction-list-item [{:keys [to value timestamp] :as transaction}]
[recipient [:contact-by-address to]] [recipient [:contact-by-address to]]
@ -144,17 +153,13 @@
(defn options-btn [] (defn options-btn []
[view {:style st/options-button} [view {:style st/options-button}
[touchable-highlight [touchable-highlight
{:on-press (fn [] {:on-press navigate-to-profile}
(close-drawer)
(rf/dispatch [:navigate-to :my-profile]))}
[view [vi/icon :icons/options]]]]) [view [vi/icon :icons/options]]]])
(defn switch-account [] (defn switch-account []
[view st/switch-account-container [view st/switch-account-container
[touchable-highlight [touchable-highlight
{:on-press (fn [] {:on-press navigate-to-accounts}
(close-drawer)
(rf/dispatch [:navigate-to :accounts]))}
[view [view
[text {:style st/switch-account-text [text {:style st/switch-account-text
:font (if platform/android? :medium :default) :font (if platform/android? :medium :default)

View File

@ -5,7 +5,7 @@
[status-im.components.renderers.renderers :as renderers] [status-im.components.renderers.renderers :as renderers]
[status-im.components.react :as react] [status-im.components.react :as react]
[status-im.components.native-action-button :refer [native-action-button]] [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.styles :refer [color-blue]]
[status-im.components.status-bar :refer [status-bar]] [status-im.components.status-bar :refer [status-bar]]
[status-im.components.toolbar-new.view :as toolbar] [status-im.components.toolbar-new.view :as toolbar]
@ -39,7 +39,7 @@
(defn toolbar-view [] (defn toolbar-view []
[toolbar/toolbar2 {} [toolbar/toolbar2 {}
[toolbar/nav-button (act/hamburger open-drawer)] [toolbar/nav-button (act/hamburger open-drawer!)]
[toolbar/content-title (i18n/label :t/chats)] [toolbar/content-title (i18n/label :t/chats)]
[toolbar/actions [toolbar/actions
(if ios? (if ios?

View File

@ -8,7 +8,7 @@
native-action-button-item]] native-action-button-item]]
[status-im.components.toolbar-new.view :as toolbar] [status-im.components.toolbar-new.view :as toolbar]
[status-im.components.toolbar-new.actions :as act] [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.icons.custom-icons :refer [ion-icon]]
[status-im.components.contact.contact :refer [contact-view]] [status-im.components.contact.contact :refer [contact-view]]
[status-im.utils.platform :refer [platform-specific ios? android?]] [status-im.utils.platform :refer [platform-specific ios? android?]]
@ -32,7 +32,7 @@
(defn toolbar-view [] (defn toolbar-view []
[toolbar/toolbar2 {} [toolbar/toolbar2 {}
[toolbar/nav-button (act/hamburger open-drawer)] [toolbar/nav-button (act/hamburger open-drawer!)]
[toolbar/content-title (label :t/contacts)] [toolbar/content-title (label :t/contacts)]
[toolbar/actions [toolbar/actions
(toolbar-actions)]]) (toolbar-actions)]])
@ -44,9 +44,9 @@
(defn contact-options [{:keys [unremovable?] :as contact} group] (defn contact-options [{:keys [unremovable?] :as contact} group]
(let [delete-contact-opt {:value #(u/show-confirmation (let [delete-contact-opt {:value #(u/show-confirmation
(str (label :t/delete-contact) "?") (label :t/delete-contact-confirmation) (str (label :t/delete-contact) "?") (label :t/delete-contact-confirmation)
(label :t/delete) (label :t/delete)
(fn [] (dispatch [:hide-contact contact]))) (fn [] (dispatch [:hide-contact contact])))
:text (label :t/delete-contact) :text (label :t/delete-contact)
:destructive? true} :destructive? true}
options (if unremovable? [] [delete-contact-opt])] options (if unremovable? [] [delete-contact-opt])]
@ -70,17 +70,17 @@
[view st/contacts-list [view st/contacts-list
[common/list-footer] [common/list-footer]
(doall (doall
(map (fn [contact] (map (fn [contact]
^{:key contact} ^{:key contact}
[view [view
[contact-view [contact-view
{:contact contact {:contact contact
:extended? edit? :extended? edit?
:on-press #(dispatch [:open-chat-with-contact %]) :on-press #(dispatch [:open-chat-with-contact %])
:extend-options (contact-options contact group)}] :extend-options (contact-options contact group)}]
(when-not (= contact (last contacts)) (when-not (= contact (last contacts))
[common/list-separator])]) [common/list-separator])])
contacts))] contacts))]
(when (< contacts-limit contacts-count) (when (< contacts-limit contacts-count)
[view [view
[common/list-separator] [common/list-separator]

View File

@ -27,11 +27,6 @@
:current-chat-id console-chat-id :current-chat-id console-chat-id
:loading-allowed true :loading-allowed true
:selected-participants #{} :selected-participants #{}
:my-profile/edit {:edit? false
:name nil
:email nil
:status nil
:photo-path nil}
:discoveries {} :discoveries {}
:discover-search-tags '() :discover-search-tags '()
:tags [] :tags []
@ -105,7 +100,9 @@
:accounts/current-account-id :accounts/current-account-id
:accounts/recover :accounts/recover
:accounts/login :accounts/login
:my-profile/edit] :my-profile/drawer
:my-profile/profile
:my-profile/default-name]
:opt-un :opt-un
[::current-public-key [::current-public-key
::modal ::modal

View File

@ -1,23 +1,23 @@
(ns status-im.ui.screens.discover.views (ns status-im.ui.screens.discover.views
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require (:require
[re-frame.core :refer [dispatch subscribe]] [re-frame.core :refer [dispatch subscribe]]
[clojure.string :as str] [clojure.string :as str]
[status-im.components.react :refer [view [status-im.components.react :refer [view
scroll-view scroll-view
text text
text-input]] text-input]]
[status-im.components.icons.vector-icons :as vi] [status-im.components.icons.vector-icons :as vi]
[status-im.components.toolbar-new.view :refer [toolbar-with-search]] [status-im.components.toolbar-new.view :refer [toolbar-with-search]]
[status-im.components.toolbar-new.actions :as act] [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.carousel.carousel :refer [carousel]] [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.popular-list :refer [discover-popular-list]]
[status-im.ui.screens.discover.views.discover-list-item :refer [discover-list-item]] [status-im.ui.screens.discover.views.discover-list-item :refer [discover-list-item]]
[status-im.utils.platform :refer [platform-specific]] [status-im.utils.platform :refer [platform-specific]]
[status-im.i18n :refer [label]] [status-im.i18n :refer [label]]
[status-im.ui.screens.discover.styles :as st] [status-im.ui.screens.discover.styles :as st]
[status-im.ui.screens.contacts.styles :as contacts-st])) [status-im.ui.screens.contacts.styles :as contacts-st]))
(defn get-hashtags [status] (defn get-hashtags [status]
(let [hashtags (map #(str/lower-case (str/replace % #"#" "")) (re-seq #"[^ !?,;:.]+" status))] (let [hashtags (map #(str/lower-case (str/replace % #"#" "")) (re-seq #"[^ !?,;:.]+" status))]
@ -30,7 +30,7 @@
:search-key :discover :search-key :discover
:title (label :t/discover) :title (label :t/discover)
:search-placeholder (label :t/search-tags) :search-placeholder (label :t/search-tags)
:nav-action (act/hamburger open-drawer) :nav-action (act/hamburger drawer/open-drawer!)
:on-search-submit (fn [text] :on-search-submit (fn [text]
(when-not (str/blank? text) (when-not (str/blank? text)
(let [hashtags (get-hashtags text)] (let [hashtags (get-hashtags text)]

View File

@ -6,6 +6,8 @@
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.utils.homoglyph :as homoglyph])) [status-im.utils.homoglyph :as homoglyph]))
(def account-profile-keys [:name :photo-path :status])
(defn correct-name? [username] (defn correct-name? [username]
(when-let [username (some-> username (string/trim))] (when-let [username (some-> username (string/trim))]
(every? false? (every? false?
@ -24,22 +26,13 @@
(or (string/starts-with? photo-path "data:image/jpeg;base64,") (or (string/starts-with? photo-path "data:image/jpeg;base64,")
(string/starts-with? photo-path "data:image/png;base64,"))) (string/starts-with? photo-path "data:image/png;base64,")))
(spec/def :profile/name correct-name?)
(spec/def :profile/name (spec/nilable correct-name?)) (spec/def :profile/status (spec/nilable string?))
(spec/def :profile/photo-path (spec/nilable base64-encoded-image-path?))
(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?)
;; EDIT PROFILE ;; EDIT PROFILE
(spec/def :my-profile/edit (allowed-keys (spec/def :my-profile/default-name string?)
:req-un [::email ::edit? ::name ::status ::photo-path] (spec/def :my-profile/profile (spec/keys :opt-un [::name :profile/status :profile/photo-path
:opt-un [::edit-status?])) ::edit-status? ::valid-name?]))
(spec/def :my-profile/drawer (spec/keys :opt-un [::name :profile/status
::edit-status? ::valid-name?]))

View File

@ -24,11 +24,15 @@
:actions [{:image :blank}]}]) :actions [{:image :blank}]}])
(defview profile-name-input [] (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 [react/view
[text-input-with-label {:label (label :t/name) [text-input-with-label
:default-value new-profile-name {:label (label :t/name)
:on-change-text #(dispatch [:set-in [:my-profile/edit :name] %])}]])) :default-value profile-name
:on-focus #(dispatch [:my-profile/edit-profile])
:on-change-text #(dispatch [:my-profile/update-name %])}]]))
(def profile-icon-options (def profile-icon-options
[{:text (label :t/image-source-gallery) [{:text (label :t/image-source-gallery)
@ -39,9 +43,10 @@
[:camera :write-external-storage] [:camera :write-external-storage]
(fn [] (fn []
(camera/request-access (camera/request-access
#(if % (dispatch [:navigate-to :profile-photo-capture]) #(if %
(utils/show-popup (label :t/error) (dispatch [:navigate-to :profile-photo-capture])
(label :t/camera-access-error)))))]))}]) (utils/show-popup (label :t/error)
(label :t/camera-access-error)))))]))}])
(defn edit-profile-badge [contact] (defn edit-profile-badge [contact]
[react/view styles/edit-profile-badge [react/view styles/edit-profile-badge
@ -54,24 +59,21 @@
[react/view styles/edit-profile-name-container [react/view styles/edit-profile-name-container
[profile-name-input]]]) [profile-name-input]]])
(defn edit-profile-status [{:keys [status edit-status?]}] (defview edit-profile-status []
(let [input-ref (reagent/atom nil)] (letsubs [edit-status? [:my-profile/get :edit-status?]
status [:my-profile/get :status]]
[react/view styles/edit-profile-status [react/view styles/edit-profile-status
[react/scroll-view [react/scroll-view
(if edit-status? (if edit-status?
[react/text-input [react/text-input
{:ref #(reset! input-ref %) {:auto-focus (if edit-status? true false)
:auto-focus edit-status?
:multiline true :multiline true
:max-length 140 :max-length 140
:placeholder (label :t/status) :placeholder (label :t/status)
:style styles/profile-status-input :style styles/profile-status-input
:on-change-text #(dispatch [:set-in [:my-profile/edit :status] (clean-text %)]) :on-change-text #(dispatch [:my-profile/update-status %])
:on-blur #(dispatch [:set-in [:my-profile/edit :edit-status?] false])
:blur-on-submit true
:on-submit-editing #(.blur @input-ref)
:default-value 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 [react/view
(if (string/blank? status) (if (string/blank? status)
[react/text {:style styles/add-a-status} [react/text {:style styles/add-a-status}
@ -86,19 +88,16 @@
(colorize-status-hashtags (label :t/status-prompt))]])) (colorize-status-hashtags (label :t/status-prompt))]]))
(defview edit-my-profile [] (defview edit-my-profile []
(letsubs [current-account [:get-current-account] (letsubs [current-account [:get-current-account]
changed-account [:get :my-profile/edit]] changed-account [:get :my-profile/profile]
{:component-will-unmount #(dispatch [:set-in [:my-profile/edit :edit-status?] false])} profile-changed? [:my-profile/changed?]
(let [profile-edit-data-valid? (spec/valid? ::db/profile changed-account) valid-name? [:my-profile/valid-name?]]
profile-edit-data-changed? (or (not= (:name current-account) (:name changed-account)) [react/keyboard-avoiding-view {:style styles/profile}
(not= (:status current-account) (:status changed-account)) [status-bar]
(not= (:photo-path current-account) (:photo-path changed-account)))] [edit-my-profile-toolbar]
[react/keyboard-avoiding-view {:style styles/profile} [react/view styles/edit-my-profile-form
[status-bar] [edit-profile-badge changed-account]
[edit-my-profile-toolbar] [edit-profile-status]
[react/view styles/edit-my-profile-form [status-prompt changed-account]]
[edit-profile-badge changed-account] (when (and valid-name? profile-changed?)
[edit-profile-status changed-account] [sticky-button (label :t/save) #(dispatch [:my-profile/save-profile])])]))
[status-prompt changed-account]]
(when (and profile-edit-data-changed? profile-edit-data-valid?)
[sticky-button (label :t/save) #(dispatch [:my-profile/save-changes])])])))

View File

@ -1,15 +1,17 @@
(ns status-im.ui.screens.profile.events (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]] [re-frame.core :as re-frame :refer [reg-fx]]
[status-im.components.react :refer [show-image-picker]] [status-im.components.react :refer [show-image-picker]]
[status-im.constants :refer [console-chat-id]] [status-im.constants :refer [console-chat-id]]
[status-im.ui.screens.profile.db :as db]
[status-im.ui.screens.profile.navigation] [status-im.ui.screens.profile.navigation]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.image-processing :refer [img->base64]] [status-im.utils.image-processing :refer [img->base64]]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
(def account-profile-keys [:name :photo-path :status])
(reg-fx (reg-fx
:open-image-picker :open-image-picker
;; the image picker is only used here for now, this effect can be use in other scenarios as well ;; 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 (when identity
{:dispatch [:navigation-replace :chat 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 (handlers/register-handler-fx
:my-profile/update-phone-number :my-profile/update-phone-number
;; Switch user to the console issuing the !phone command automatically to let him change his 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] {:dispatch-n [[:navigate-to :chat console-chat-id]
[:select-chat-input-command {:name "phone"}]]})) [: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 (handlers/register-handler-fx
:my-profile/update-picture :my-profile/update-picture
(fn [{:keys [db]} [this-event base64-image]] (fn [{:keys [db]} [this-event base64-image]]
(if 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}))) {: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 (handlers/register-handler-fx
:my-profile/save-changes :my-profile.drawer/save-name
(fn [{:keys [db]} _] (fn [{:keys [db]} _]
(let [{:keys [:my-profile/edit]} db] (let [cleaned-name (clean-name db :my-profile/drawer)]
{:dispatch-n [[:check-status-change (:status edit)] {:db (clear-profile db)
[:account-update (select-keys edit account-profile-keys)]]}))) :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]]})))

View File

@ -18,7 +18,7 @@
_ (log/debug "Captured image: " path) _ (log/debug "Captured image: " path)
on-success (fn [base64] on-success (fn [base64]
(log/debug "Captured success: " 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])) (dispatch [:navigate-back]))
on-error (fn [type error] on-error (fn [type error]
(log/debug type error))] (log/debug type error))]

View File

@ -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)))

View File

@ -24,8 +24,8 @@
(:require-macros [status-im.utils.views :refer [defview]])) (:require-macros [status-im.utils.views :refer [defview]]))
(defn my-profile-toolbar [] (defn my-profile-toolbar []
[toolbar/toolbar {:actions [(actions/opts [{:value #(dispatch [:my-profile/edit]) [toolbar/toolbar {:actions [(actions/opts [{:value #(dispatch [:my-profile/edit-profile])
:text (label :t/edit)}])]}]) :text (label :t/edit)}])]}])
(defn profile-toolbar [contact] (defn profile-toolbar [contact]
[toolbar/toolbar [toolbar/toolbar
@ -172,12 +172,12 @@
(defn profile-status [status & [edit?]] (defn profile-status [status & [edit?]]
[react/view styles/profile-status-container [react/view styles/profile-status-container
(if (or (nil? status) (string/blank? status)) (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/view
[react/text {:style styles/add-a-status} [react/text {:style styles/add-a-status}
(label :t/add-a-status)]]] (label :t/add-a-status)]]]
[react/scroll-view [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/view
[react/text {:style styles/profile-status-text} [react/text {:style styles/profile-status-text}
(colorize-status-hashtags status)]]]])]) (colorize-status-hashtags status)]]]])])

View File

@ -7,6 +7,7 @@
status-im.ui.screens.discover.subs status-im.ui.screens.discover.subs
status-im.ui.screens.contacts.subs status-im.ui.screens.contacts.subs
status-im.ui.screens.group.subs status-im.ui.screens.group.subs
status-im.ui.screens.profile.subs
status-im.ui.screens.wallet.subs status-im.ui.screens.wallet.subs
status-im.transactions.subs status-im.transactions.subs
status-im.bots.subs)) status-im.bots.subs))
@ -39,4 +40,4 @@
(fn [[search-mode? chats-edit-mode? contacts-edit-mode? view-id]] (fn [[search-mode? chats-edit-mode? contacts-edit-mode? view-id]]
(or search-mode? (or search-mode?
(and (= view-id :chat-list) chats-edit-mode?) (and (= view-id :chat-list) chats-edit-mode?)
(and (= view-id :contact-list) contacts-edit-mode?)))) (and (= view-id :contact-list) contacts-edit-mode?))))

View File

@ -42,7 +42,7 @@
(defn toolbar-view [] (defn toolbar-view []
[toolbar/toolbar2 {:style wallet-styles/toolbar} [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-title]
[toolbar/actions [toolbar/actions
[(assoc (act/opts [{:text (i18n/label :t/wallet-settings) :value show-not-implemented!}]) :icon-opts {:color :white}) [(assoc (act/opts [{:text (i18n/label :t/wallet-settings) :value show-not-implemented!}]) :icon-opts {:color :white})

View File

@ -29,26 +29,28 @@
(run-test-sync (run-test-sync
(test-fixtures) (test-fixtures)
(let [accounts (rf/subscribe [:get-accounts]) (let [accounts (rf/subscribe [:get-accounts])
address (:address new-account) address (:address new-account)]
new-status "It's a new status!"]
(rf/dispatch [:initialize-db]) (rf/dispatch [:initialize-db])
(rf/dispatch [:add-account new-account]) (rf/dispatch [:add-account new-account])
(rf/dispatch [:set-current-account address]) (rf/dispatch [:set-current-account address])
(testing "Setting status"
(is (= (:status new-account) (-> @accounts (testing "Setting status from edit profile screen"
(get address) (let [new-status "New edit profile status"]
:status))) (is (= (:status new-account) (-> @accounts
(rf/dispatch [:my-profile/update-status new-status]) (get address)
(is (= new-status (-> @accounts :status)))
(get address) (rf/dispatch [:my-profile/edit-profile :edit-status])
:status)))) (rf/dispatch [:my-profile/update-status new-status])
(testing "Setting phone number" (rf/dispatch [:my-profile/save-profile])
(is (nil? (-> @accounts (is (= new-status (-> @accounts
(get address) (get address)
:phone))) :status)))))
(rf/dispatch [:set-in [:my-profile/edit :edit-status?] true])
(rf/dispatch [:set-in [:my-profile/edit :name] "It's my new name"]) (testing "Setting status from drawer"
(rf/dispatch [:my-profile/save-changes]) (let [new-status "New drawer status"]
(is (= "It's my new name" (-> @accounts (rf/dispatch [:my-profile.drawer/edit-status])
(get address) (rf/dispatch [:my-profile.drawer/update-status new-status])
:name))))))) (rf/dispatch [:my-profile.drawer/save-status])
(is (= new-status (-> @accounts
(get address)
:status))))))))