Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support hooks OR atom state management in component previews #20053

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/status_im/contexts/preview/quo/counter/step.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns status-im.contexts.preview.quo.counter.step
(:require
[quo.core :as quo]
[reagent.core :as reagent]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))

(def descriptor
Expand All @@ -17,13 +17,13 @@

(defn view
[]
(let [state (reagent/atom {:value "5"
:type :neutral
:in-blur-view? false})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:in-blur-view? @state)
:show-blur-background? (:in-blur-view? @state)}
[quo/step (dissoc @state :value) (:value @state)]])))
(let [[state set-state] (rn/use-state {:value "5"
:type :neutral
:in-blur-view? false})]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor
:blur? (:in-blur-view? state)
:show-blur-background? (:in-blur-view? state)}
[quo/step (dissoc state :value) (:value state)]]))
190 changes: 118 additions & 72 deletions src/status_im/contexts/preview/quo/preview.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -46,70 +46,94 @@
(str (humanize k) ":"))

(defn- customizer-boolean
[{:keys [label state] :as args}]
(let [theme (quo.theme/use-theme)
label (or label (key->boolean-label (:key args)))
field-value (reagent/cursor state [(:key args)])
active? @field-value]
[{:keys [label state set-state] :as args}]
(let [theme (quo.theme/use-theme)
label (or label (key->boolean-label (:key args)))
field-cursor (when-not (fn? set-state)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: As a temporary solution until we update all component previews, we check if set-state is a function and use that instead of the Reagent atom. This is how we support both APIs.

I didn't bother making things pretty and copy & pasted more because most of this will go away anyway.

(reagent/cursor state [(:key args)]))
field-value (if (fn? set-state)
(get state (:key args))
@field-cursor)
set-field-value (fn [value]
(if (fn? set-state)
(set-state (assoc state (:key args) value))
(reset! field-cursor value)))]
[rn/view {:style style/field-row}
[label-view state label theme]
[rn/view {:style (style/boolean-container)}
[rn/pressable
{:style (style/boolean-button {:active? active? :left? true} theme)
:on-press #(reset! field-value true)}
[rn/text {:style (style/field-text active? theme)}
{:style (style/boolean-button {:active? field-value :left? true} theme)
:on-press #(set-field-value true)}
[rn/text {:style (style/field-text field-value theme)}
"True"]]
[rn/pressable
{:style (style/boolean-button {:active? (not active?) :left? false} theme)
:on-press #(reset! field-value false)}
[rn/text {:style (style/field-text (not active?) theme)}
{:style (style/boolean-button {:active? (not field-value) :left? false} theme)
:on-press #(set-field-value false)}
[rn/text {:style (style/field-text (not field-value) theme)}
"False"]]]]))

(defn- customizer-text
[{:keys [label state limit suffix] :as args} theme]
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[{:keys [label state set-state limit suffix] :as args} theme]
(let [label (or label (key->text-label (:key args)))
field-cursor (when-not (fn? set-state)
(reagent/cursor state [(:key args)]))
field-value (if (fn? set-state)
(get state (:key args))
@field-cursor)
set-field-value (fn [value]
(if (fn? set-state)
(set-state (assoc state (:key args) value))
(reset! field-cursor value)))]
[rn/view {:style style/field-row}
[label-view state label theme]
[rn/view {:style style/field-column}
[rn/text-input
(merge
{:value @field-value
{:value field-value
:show-cancel false
:style (style/field-container false theme)
:keyboard-appearance theme
:on-change-text (fn [text]
(reset! field-value (if (and suffix
(> (count text) (count @field-value)))
(str (string/replace text suffix "") suffix)
text))
(reagent/flush))}
(set-field-value (if (and suffix
(> (count text) (count field-value)))
(str (string/replace text suffix "") suffix)
text))
(when-not (fn? set-state)
(reagent/flush)))}
(when limit
{:max-length limit}))]]]))

(defn- customizer-number
[{:keys [label state default] :as args} theme]
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[{:keys [label state set-state default] :as args} theme]
(let [label (or label (key->text-label (:key args)))
field-cursor (when-not (fn? set-state)
(reagent/cursor state [(:key args)]))
field-value (if (fn? set-state)
(get state (:key args))
@field-cursor)
set-field-value (fn [value]
(if (fn? set-state)
(set-state (assoc state (:key args) value))
(reset! field-cursor value)))]
[rn/view {:style style/field-row}
[label-view state label theme]
[rn/view {:style style/field-column}
[rn/text-input
(merge
{:value (str @field-value)
:show-cancel false
:style (style/field-container false theme)
:keyboard-appearance theme
:on-change-text (fn [text]
(reset! field-value (utils.number/parse-int text default))
(reagent/flush))})]]]))
{:value (str field-value)
:show-cancel false
:style (style/field-container false theme)
:keyboard-appearance theme
:on-change-text (fn [text]
(set-field-value (utils.number/parse-int text default))
(when-not (fn? set-state)
(reagent/flush)))}]]]))

(defn- find-selected-option
[id v]
(first (filter #(= (:key %) id) v)))

(defn- customizer-select-modal
[{:keys [open options field-value]}]
[{:keys [open options field-value set-field-value]}]
(let [theme (quo.theme/use-theme)]
[rn/modal
{:visible @open
Expand All @@ -125,17 +149,17 @@
:let [v (or v (humanize k))]]
^{:key k}
[rn/pressable
{:style (style/select-option (= @field-value k) theme)
{:style (style/select-option (= field-value k) theme)
:on-press (fn []
(reset! open false)
(reset! field-value k))}
[rn/text {:style (style/field-text (= @field-value k) theme)}
(set-field-value k))}
[rn/text {:style (style/field-text (= field-value k) theme)}
v]]))]
[rn/view {:style (style/footer theme)}
[rn/pressable
{:style (style/select-button theme)
:on-press (fn []
(reset! field-value nil)
(set-field-value nil)
(reset! open false))}
[rn/text {:style (style/field-text false theme)}
"Clear"]]
Expand Down Expand Up @@ -163,22 +187,31 @@
(defn- customizer-select
[]
(let [open (reagent/atom nil)]
(fn [{:keys [label state options] :as args}]
(fn [{:keys [label state set-state options] :as args}]
(let [theme (quo.theme/use-theme)
label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])
selected-option (find-selected-option @field-value options)]
field-cursor (when-not (fn? set-state)
(reagent/cursor state [(:key args)]))
field-value (if (fn? set-state)
(get state (:key args))
@field-cursor)
set-field-value (fn [value]
(if (fn? set-state)
(set-state (assoc state (:key args) value))
(reset! field-cursor value)))
selected-option (find-selected-option field-value options)]
[rn/view {:style style/field-row}
[label-view state label theme]
[rn/view {:style style/field-column}
[customizer-select-modal
{:open open
:options options
:field-value field-value}]
{:open open
:options options
:field-value field-value
:set-field-value set-field-value}]
[customizer-select-button {:open open :selected-option selected-option} theme]]]))))

(defn- customizer-multi-select-modal
[{:keys [open-atom options selected-keys-atom]}]
[{:keys [open-atom options field-value set-field-value]}]
(let [theme (quo.theme/use-theme)]
[rn/modal
{:visible @open-atom
Expand All @@ -193,13 +226,13 @@
(for [{k :key v :value} options
:let [v (or v (humanize k))]]
^{:key k}

(let [checked? (boolean (some #(= k %) @selected-keys-atom))
(let [checked? (boolean (some #(= k %) field-value))
remove-key (fn [v] (filterv #(not= % k) v))
on-press (fn []
(swap! selected-keys-atom
(if checked? remove-key conj)
k))]
(set-field-value
(if checked?
(remove-key field-value)
(conj field-value k))))]
[rn/pressable
{:style (style/multi-select-option theme)
:on-press on-press}
Expand All @@ -212,7 +245,7 @@
[rn/pressable
{:style (style/select-button theme)
:on-press (fn []
(reset! selected-keys-atom nil)
(set-field-value nil)
(reset! open-atom false))}
[rn/text {:style (style/field-text false theme)}
"Clear"]]
Expand Down Expand Up @@ -246,41 +279,51 @@
(defn- customizer-multi-select
[]
(let [open (reagent/atom nil)]
(fn [{:keys [label state options] :as args}]
(fn [{:keys [label state set-state options] :as args}]
(let [theme (quo.theme/use-theme)
label (or label (key->text-label (:key args)))
selected-keys (reagent/cursor state [(:key args)])
selected-options (filter-by-keys options @selected-keys)]
field-cursor (when-not (fn? set-state)
(reagent/cursor state [(:key args)]))
field-value (if (fn? set-state)
(get state (:key args))
@field-cursor)
set-field-value (fn [value]
(if (fn? set-state)
(set-state (assoc state (:key args) value))
(reset! field-cursor value)))
selected-options (filter-by-keys options field-value)]
[rn/view {:style style/field-row}
[label-view state label theme]
[rn/view {:style style/field-column}
[customizer-multi-select-modal
{:open-atom open
:selected-keys-atom selected-keys
:options options}]
{:open-atom open
:field-value field-value
:set-field-value set-field-value
:options options}]
[customizer-multi-select-button {:open open :selected-options selected-options} theme]]]))))

(defn customizer
[state descriptors theme]
[state set-state descriptors theme]
[rn/view
{:style {:flex-shrink 1
:padding-horizontal 20}}
(doall
(for [desc descriptors
:let [desc-path (:path desc)
new-state (if desc-path
(reagent/cursor state desc-path)
state)
descriptor (assoc desc :state new-state)]]
descriptor (if (fn? set-state)
(assoc desc :state state :set-state set-state)
(let [new-state (if desc-path
(reagent/cursor state desc-path)
state)]
(assoc desc :state new-state)))]]
^{:key (:key desc)}
[:<>
(case (:type desc)
:boolean [customizer-boolean descriptor]
:text [customizer-text descriptor theme]
:number [customizer-number descriptor theme]
:select [customizer-select descriptor]
:multi-select [customizer-multi-select descriptor]
nil)]))])
(case (:type desc)
:boolean [customizer-boolean descriptor]
:text [customizer-text descriptor theme]
:number [customizer-number descriptor theme]
:select [customizer-select descriptor]
:multi-select [customizer-multi-select descriptor]
nil)))])

(defn customization-color-option
([]
Expand Down Expand Up @@ -325,7 +368,7 @@
children)])

(defn- f-preview-container
[{:keys [title state descriptor blur? blur-dark-only?
[{:keys [title state set-state descriptor blur? blur-dark-only?
component-container-style
blur-container-style blur-view-props blur-height show-blur-background? full-screen?]
:or {blur-height 200}}
Expand All @@ -352,7 +395,7 @@
:on-press rn/dismiss-keyboard!}
(when descriptor
[rn/view {:style style/customizer-container}
[customizer state descriptor theme]])
[customizer state set-state descriptor theme]])
(if blur?
[rn/view {:style (merge style/component-container component-container-style)}
(into [blur-view
Expand All @@ -371,8 +414,11 @@
(into [rn/view {:style (merge style/component-container component-container-style)}]
children))]
(when state
(let [decr-state (if descriptor (select-keys @state (mapv :key (flatten descriptor))) @state)
state-str (with-out-str (cljs.pprint/pprint decr-state))]
(let [actual-state (if (fn? set-state) state @state)
decr-state (if descriptor
(select-keys actual-state (mapv :key (flatten descriptor)))
actual-state)
state-str (with-out-str (cljs.pprint/pprint decr-state))]
[rn/view {:style {:margin 50}}
[quo/text {:style {:margin-bottom 10}} "State map (click on map to copy)"]
[rn/pressable
Expand Down
Loading