migrating to react state. step 1 (#18901)

This commit is contained in:
flexsurfer 2024-02-28 11:48:23 +01:00 committed by GitHub
parent acc6a3c072
commit 047e45d2a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 482 additions and 530 deletions

View File

@ -6,8 +6,7 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform] [react-native.platform :as platform]))
[reagent.core :as reagent]))
(defn remove-http-https-www (defn remove-http-https-www
[value] [value]
@ -68,78 +67,86 @@
[:cursor-color :placeholder-text-color :editable :on-change-text :on-focus [:cursor-color :placeholder-text-color :editable :on-change-text :on-focus
:on-blur :on-clear :value :disabled? :blur? :customization-color :theme]) :on-blur :on-clear :value :disabled? :blur? :customization-color :theme])
(defn- view-internal (defn view
[{:keys [default-value] [{:keys [disabled? blur? on-change-text customization-color
:or {default-value ""}}] on-clear on-focus on-blur get-ref locked?
(let [state (reagent/atom :default) favicon favicon-color favicon-size default-value]
value (reagent/atom default-value) :or {default-value ""}
set-active #(reset! state :active) :as props}]
set-default #(reset! state :default) (let [ref (rn/use-ref-atom nil)
set-value #(reset! value %) on-ref (rn/use-callback
ref (atom nil) (fn [r]
clear-input (fn [] (reset! ref r)
(.clear ^js @ref) (when get-ref (get-ref r)))
(reset! value "")) [get-ref])
focus-input (fn [] theme (quo.theme/use-theme)
(set-active) [state set-state] (rn/use-state :default)
(.focus ^js @ref))] [value set-value] (rn/use-state default-value)
(fn [{:keys [disabled? blur? on-change-text customization-color on-clear (rn/use-callback
on-clear on-focus on-blur theme get-ref locked? (fn []
favicon favicon-color favicon-size] (.clear ^js @ref)
:as props}] (set-value "")
(let [clean-props (apply dissoc props props-to-remove)] (when on-clear (on-clear)))
[rn/view {:style style/root-container} [on-clear])
(when (and (seq @value) (= @state :default)) focus-input (rn/use-callback
[rn/touchable-opacity (fn []
{:style style/default-container (set-state :active)
:on-press focus-input} (.focus ^js @ref)))
(when favicon on-blur (rn/use-callback
[icon/icon favicon (fn []
{:accessibility-label :browser-input-favicon (set-state :default)
:color favicon-color (when on-blur (on-blur)))
:container-style style/favicon-icon-container [on-blur])
:size favicon-size}]) on-change-text (rn/use-callback
[rn/text (fn [new-text]
{:accessibility-label :browser-input-label (set-value new-text)
:style (style/text)} (remove-http-https-www @value)] (when on-change-text (on-change-text new-text)))
(when locked? [on-change-text])
[lock-icon on-focus (rn/use-callback
{:blur? blur? (fn []
:theme theme}])]) (set-state :active)
[rn/view {:style (style/active-container (or (empty? @value) (= @state :active)))} (when on-focus (on-focus)))
[rn/text-input [on-focus])
(merge clean-props (apply dissoc props props-to-remove)]
clean-props [rn/view {:style style/root-container}
{:accessibility-label :browser-input (when (and (seq value) (= state :default))
:auto-capitalize :none [rn/touchable-opacity
:auto-correct false {:style style/default-container
:cursor-color (cursor-color customization-color theme) :on-press focus-input}
:editable (not disabled?) (when favicon
:keyboard-appearance (colors/theme-colors :light :dark theme) [icon/icon favicon
:keyboard-type :web-search {:accessibility-label :browser-input-favicon
:on-blur (fn [] :color favicon-color
(set-default) :container-style style/favicon-icon-container
(when on-blur (on-blur))) :size favicon-size}])
:on-change-text (fn [new-text] [rn/text
(set-value new-text) {:accessibility-label :browser-input-label
(when on-change-text (on-change-text new-text))) :style (style/text)}
:on-focus (fn [] (remove-http-https-www value)]
(set-active) (when locked?
(when on-focus (on-focus))) [lock-icon {:blur? blur? :theme theme}])])
:placeholder-text-color (placeholder-color @state blur? theme) [rn/view {:style (style/active-container (or (empty? value) (= state :active)))}
:ref (fn [r] [rn/text-input
(reset! ref r) (merge
(when get-ref (get-ref r))) clean-props
:selection-color (when platform/ios? {:accessibility-label :browser-input
(cursor-color customization-color theme)) :auto-capitalize :none
:select-text-on-focus true :auto-correct false
:style (style/input disabled?)})] :cursor-color (cursor-color customization-color theme)
(when (seq @value) :editable (not disabled?)
[clear-button :keyboard-appearance (colors/theme-colors :light :dark theme)
{:blur? blur? :keyboard-type :web-search
:on-press (fn [] :on-blur on-blur
(clear-input) :on-change-text on-change-text
(when on-clear (on-clear))) :on-focus on-focus
:theme theme}])]])))) :placeholder-text-color (placeholder-color state blur? theme)
:ref on-ref
(def view (quo.theme/with-theme view-internal)) :selection-color (when platform/ios?
(cursor-color customization-color theme))
:select-text-on-focus true
:style (style/input disabled?)})]
(when (seq value)
[clear-button
{:blur? blur?
:on-press on-clear
:theme theme}])]]))

View File

@ -7,10 +7,9 @@
[quo.foundations.customization-colors :as customization-colors] [quo.foundations.customization-colors :as customization-colors]
[quo.theme :as theme] [quo.theme :as theme]
[react-native.blur :as blur] [react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- button-internal (defn button
"with label "with label
[button opts \"label\"] [button opts \"label\"]
opts opts
@ -29,102 +28,103 @@
:theme :light/:dark :theme :light/:dark
only icon only icon
[button {:icon-only? true} :i/close-circle]" [button {:icon-only? true} :i/close-circle]"
[_ _] [{:keys [on-press on-long-press disabled? type background size icon-left icon-right icon-top
(let [pressed-state? (reagent/atom false)] customization-color accessibility-label icon-only? container-style inner-style
(fn pressed? on-press-in on-press-out allow-multiple-presses?]
[{:keys [on-press on-long-press disabled? type background size icon-left icon-right icon-top :or {type :primary
customization-color theme accessibility-label icon-only? container-style inner-style size 40
pressed? on-press-in on-press-out allow-multiple-presses?] customization-color (if (= type :primary) :blue nil)}}
:or {type :primary children]
size 40 (let [[pressed-state? set-pressed-state] (rn/use-state false)
customization-color (if (= type :primary) :blue nil)}} theme (theme/use-theme-value)
children] {:keys [icon-color background-color label-color border-color blur-type
(let [{:keys [icon-color background-color label-color border-color blur-type blur-overlay-color border-radius overlay-customization-color]}
blur-overlay-color border-radius overlay-customization-color]} (button-properties/get-values {:customization-color customization-color
(button-properties/get-values {:customization-color customization-color :background background
:background background :type type
:type type :theme theme
:theme theme :pressed? (if pressed? pressed? pressed-state?)
:pressed? (if pressed? pressed? @pressed-state?) :icon-only? icon-only?})
:icon-only? icon-only?}) icon-size (when (= 24 size) 12)
icon-size (when (= 24 size) 12)] on-press-in-cb (rn/use-callback
[rn/touchable-without-feedback (fn []
{:disabled disabled? (set-pressed-state true)
:accessibility-label accessibility-label (when on-press-in (on-press-in))))
:on-press-in (fn [] on-press-out-cb (rn/use-callback
(reset! pressed-state? true) (fn []
(when on-press-in (on-press-in))) (set-pressed-state nil)
:on-press-out (fn [] (when on-press-out (on-press-out))))]
(reset! pressed-state? nil) [rn/touchable-without-feedback
(when on-press-out (on-press-out))) {:disabled disabled?
:on-press on-press :accessibility-label accessibility-label
:allow-multiple-presses? allow-multiple-presses? :on-press-in on-press-in-cb
:on-long-press on-long-press} :on-press-out on-press-out-cb
:on-press on-press
:allow-multiple-presses? allow-multiple-presses?
:on-long-press on-long-press}
[rn/view
{:style (merge
(style/shape-style-container size border-radius)
container-style)}
[rn/view
{:style (merge
(style/style-container {:size size
:disabled? disabled?
:border-radius border-radius
:background-color background-color
:border-color border-color
:icon-only? icon-only?
:icon-top icon-top
:icon-left icon-left
:icon-right icon-right})
inner-style)}
(when overlay-customization-color
[customization-colors/overlay
{:customization-color overlay-customization-color
:theme theme
:pressed? (if pressed? pressed? pressed-state?)}])
(when (= background :photo)
[blur/view
{:blur-radius 20
:blur-type blur-type
:overlay-color blur-overlay-color
:style style/blur-view}])
(when icon-top
[rn/view [rn/view
{:style (merge [quo.icons/icon icon-top
(style/shape-style-container size border-radius) {:container-style {:margin-bottom 2}
container-style)} :color icon-color
[rn/view :size icon-size}]])
{:style (merge (when icon-left
(style/style-container {:size size [rn/view
:disabled? disabled? {:style (style/icon-left-icon-style
:border-radius border-radius {:size size
:background-color background-color :icon-size icon-size})}
:border-color border-color [quo.icons/icon icon-left
:icon-only? icon-only? {:color icon-color
:icon-top icon-top :size icon-size}]])
:icon-left icon-left [rn/view
:icon-right icon-right}) (cond
inner-style)} icon-only?
(when overlay-customization-color [quo.icons/icon children
[customization-colors/overlay {:color label-color
{:customization-color overlay-customization-color :size icon-size}]
:theme theme
:pressed? (if pressed? pressed? @pressed-state?)}])
(when (= background :photo)
[blur/view
{:blur-radius 20
:blur-type blur-type
:overlay-color blur-overlay-color
:style style/blur-view}])
(when icon-top
[rn/view
[quo.icons/icon icon-top
{:container-style {:margin-bottom 2}
:color icon-color
:size icon-size}]])
(when icon-left
[rn/view
{:style (style/icon-left-icon-style
{:size size
:icon-size icon-size})}
[quo.icons/icon icon-left
{:color icon-color
:size icon-size}]])
[rn/view
(cond
icon-only?
[quo.icons/icon children
{:color label-color
:size icon-size}]
(string? children) (string? children)
[text/text [text/text
{:size (when (#{56 24} size) :paragraph-2) {:size (when (#{56 24} size) :paragraph-2)
:weight :medium :weight :medium
:number-of-lines 1 :number-of-lines 1
:style {:color label-color}} :style {:color label-color}}
children] children]
(vector? children) (vector? children)
children)] children)]
(when icon-right (when icon-right
[rn/view [rn/view
{:style (style/icon-right-icon-style {:style (style/icon-right-icon-style
{:size size {:size size
:icon-size icon-size})} :icon-size icon-size})}
[quo.icons/icon icon-right [quo.icons/icon icon-right
{:color icon-color {:color icon-color
:size icon-size}]])]]])))) :size icon-size}]])]]]))
(def button (theme/with-theme button-internal))

View File

@ -3,28 +3,24 @@
[quo.components.buttons.composer-button.style :as style] [quo.components.buttons.composer-button.style :as style]
[quo.components.icon :as quo.icons] [quo.components.icon :as quo.icons]
[quo.theme :as theme] [quo.theme :as theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- view-internal (defn view
[_ _] [{:keys [on-press on-long-press disabled? blur? icon accessibility-label container-style]}]
(let [pressed? (reagent/atom false)] (let [[pressed? set-pressed] (rn/use-state false)
(fn theme (theme/use-theme-value)
[{:keys [on-press on-long-press disabled? theme blur? icon accessibility-label container-style]}] on-press-in (rn/use-callback #(set-pressed true))
[rn/pressable on-press-out (rn/use-callback #(set-pressed nil))]
{:accessibility-label (or accessibility-label :composer-button) [rn/pressable
:on-press on-press {:accessibility-label (or accessibility-label :composer-button)
:on-press-in #(reset! pressed? true) :on-press on-press
:on-press-out #(reset! pressed? nil) :on-press-in on-press-in
:on-long-press on-long-press :on-press-out on-press-out
:disabled disabled? :on-long-press on-long-press
:style (merge (style/main {:pressed? @pressed? :disabled disabled?
:blur? blur? :style (merge (style/main {:pressed? pressed?
:theme theme :blur? blur?
:disabled? disabled?}) :theme theme
container-style)} :disabled? disabled?})
[quo.icons/icon icon container-style)}
{:color (style/get-label-color {:blur? blur? [quo.icons/icon icon {:color (style/get-label-color {:blur? blur? :theme theme})}]]))
:theme theme})}]])))
(def view (theme/with-theme view-internal))

View File

@ -5,8 +5,7 @@
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- get-button-color (defn- get-button-color
[{:keys [type pressed? customization-color theme]}] [{:keys [type pressed? customization-color theme]}]
@ -45,48 +44,48 @@
:color (get-icon-and-text-color type theme) :color (get-icon-and-text-color type theme)
:container-style (style/container type)}]) :container-style (style/container type)}])
(defn- view-internal (defn view
"[dynamic-button opts] "[dynamic-button opts]
opts opts
{:type :jump-to/:mention/:notification-down/:notification-up/:search/:search-with-label/:scroll-to-bottom {:type :jump-to/:mention/:notification-down/:notification-up/:search/:search-with-label/:scroll-to-bottom
:on-press fn :on-press fn
:count mentions or notifications count :count mentions or notifications count
:customization-color customize jump-to and mention button color}" :customization-color customize jump-to and mention button color}"
[_] [{:keys [type label on-press customization-color style] :as args}]
(let [pressed? (reagent/atom false)] (let [theme (quo.theme/use-theme-value)
(fn [{:keys [type label on-press customization-color style theme] :as args}] [pressed? set-pressed] (rn/use-state false)
[rn/touchable-opacity button-color (get-button-color {:type type
{:on-press-in #(reset! pressed? true) :pressed? pressed?
:on-press-out #(reset! pressed? false) :customization-color (or customization-color :primary)
:on-press on-press :theme theme})
:active-opacity 1 on-press-in (rn/use-callback #(set-pressed true))
:hit-slop {:top 5 :bottom 5 :left 5 :right 5} on-press-out (rn/use-callback #(set-pressed false))]
:pointer-events :auto [rn/touchable-opacity
:style {:height 24} {:on-press-in on-press-in
:accessibility-label type} :on-press-out on-press-out
[rn/view :on-press on-press
{:style (merge :active-opacity 1
{:flex-direction :row :hit-slop {:top 5 :bottom 5 :left 5 :right 5}
:height 24 :pointer-events :auto
:border-radius 12 :style {:height 24}
:background-color (get-button-color {:type type :accessibility-label type}
:pressed? @pressed? [rn/view
:customization-color (or customization-color {:style (merge
:primary) {:flex-direction :row
:theme theme})} :height 24
style)} :border-radius 12
(when (#{:mention :search :search-with-label :scroll-to-bottom} type) :background-color button-color}
[icon-view type]) style)}
(when (#{:jump-to :mention :notification-down :notification-up :search-with-label} type) (when (#{:mention :search :search-with-label :scroll-to-bottom} type)
[text/text [icon-view type])
{:weight :medium (when (#{:jump-to :mention :notification-down :notification-up :search-with-label} type)
:size :paragraph-2 [text/text
:style (assoc (style/text type) :color (get-icon-and-text-color type theme))} {:weight :medium
(case type :size :paragraph-2
:jump-to label :style (assoc (style/text type) :color (get-icon-and-text-color type theme))}
:search-with-label label (case type
(:mention :notification-down :notification-up) (str (:count args)))]) :jump-to label
(when (#{:jump-to :notification-down :notification-up} type) :search-with-label label
[icon-view type theme])]]))) (:mention :notification-down :notification-up) (str (:count args)))])
(when (#{:jump-to :notification-down :notification-up} type)
(def view (quo.theme/with-theme view-internal)) [icon-view type theme])]]))

View File

@ -6,29 +6,25 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent]
[utils.i18n :as i18n])) [utils.i18n :as i18n]))
(defn- view-internal (defn view
[_] [{:keys [on-press on-long-press disabled? container-style]}]
(let [pressed? (reagent/atom false) (let [theme (quo.theme/use-theme-value)
on-press-in #(reset! pressed? true) [pressed? set-pressed] (rn/use-state false)
on-press-out #(reset! pressed? nil)] on-press-in (rn/use-callback #(set-pressed true))
(fn on-press-out (rn/use-callback #(set-pressed nil))]
[{:keys [on-press on-long-press disabled? theme container-style]}] [rn/pressable
[rn/pressable {:accessibility-label :log-out-button
{:accessibility-label :log-out-button :on-press on-press
:on-press on-press :on-press-in on-press-in
:on-press-in on-press-in :on-press-out on-press-out
:on-press-out on-press-out :on-long-press on-long-press
:on-long-press on-long-press :disabled disabled?
:disabled disabled? :style (merge (style/main {:pressed? pressed?
:style (merge (style/main {:pressed? @pressed? :theme theme
:theme theme :disabled? disabled?})
:disabled? disabled?}) container-style)}
container-style)} [icon/icon :i/log-out {:color (if pressed? colors/white-opa-40 colors/white-opa-70)}]
[icon/icon :i/log-out {:color (if pressed? colors/white-opa-40 colors/white-opa-70)}] [text/text {:weight :medium :size :paragraph-1}
[text/text {:weight :medium :size :paragraph-1} (i18n/label :t/logout)]]))
(i18n/label :t/logout)]])))
(def view (quo.theme/with-theme view-internal))

View File

@ -1,9 +1,5 @@
(ns quo.components.buttons.slide-button.animations (ns quo.components.buttons.slide-button.animations
(:require (:require [react-native.reanimated :as reanimated]))
[oops.core :as oops]
[quo.components.buttons.slide-button.utils :as utils]
[react-native.gesture :as gesture]
[react-native.reanimated :as reanimated]))
(def ^:private extrapolation (def ^:private extrapolation
{:extrapolateLeft "clamp" {:extrapolateLeft "clamp"
@ -66,36 +62,6 @@
:damping 30 :damping 30
:stiffness 400})) :stiffness 400}))
(defn- complete-animation
[sliding-complete?]
(reset! sliding-complete? true))
(defn reset-track-position (defn reset-track-position
[x-pos] [x-pos]
(animate-spring x-pos 0)) (animate-spring x-pos 0))
;; Gestures
(defn drag-gesture
[x-pos
gestures-disabled?
disabled?
track-width
sliding-complete?]
(let [gestures-enabled? (not (or disabled? @gestures-disabled?))]
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled gestures-enabled?)
(gesture/min-distance 0)
(gesture/on-update (fn [event]
(let [x-translation (oops/oget event "translationX")
clamped-x (utils/clamp-value x-translation 0 track-width)
reached-end? (>= clamped-x track-width)]
(reanimated/set-shared-value x-pos clamped-x)
(when (and reached-end? (not @sliding-complete?))
(reset! gestures-disabled? true)
(complete-animation sliding-complete?)))))
(gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)]
(when (not reached-end?)
(reset-track-position x-pos))))))))

View File

@ -11,94 +11,35 @@
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.gesture :as gesture] [react-native.gesture :as gesture]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]))
[reagent.core :as reagent]))
(defn- f-slider (defn drag-gesture
[{:keys [disabled?]}] [x-pos gestures-disabled? set-gestures-disabled disabled? track-width sliding-complete?
(let [track-width (reagent/atom nil) set-sliding-complete
sliding-complete? (reagent/atom false) on-complete reset-fn]
gestures-disabled? (reagent/atom disabled?) (let [gestures-enabled? (not (or disabled? gestures-disabled?))]
on-track-layout (fn [evt] (-> (gesture/gesture-pan)
(let [width (oops/oget evt "nativeEvent.layout.width")] (gesture/with-test-ID :slide-button-gestures)
(reset! track-width width)))] (gesture/enabled gestures-enabled?)
(fn [{:keys [on-reset (gesture/min-distance 0)
on-complete (gesture/on-update (fn [event]
track-text (let [x-translation (oops/oget event "translationX")
track-icon clamped-x (utils/clamp-value x-translation 0 track-width)
disabled? reached-end? (>= clamped-x track-width)]
customization-color (reanimated/set-shared-value x-pos clamped-x)
size (when (and reached-end? (not sliding-complete?))
container-style (set-gestures-disabled true)
theme (set-sliding-complete true)
type (when on-complete (on-complete reset-fn))))))
blur?]}] (gesture/on-end (fn [event]
(let [x-pos (reanimated/use-shared-value 0) (let [x-translation (oops/oget event "translationX")
dimensions (partial utils/get-dimensions reached-end? (>= x-translation track-width)]
(or @track-width constants/default-width) (when (not reached-end?)
size) (animations/reset-track-position x-pos))))))))
interpolate-track (partial animations/interpolate-track
x-pos
(dimensions :usable-track)
(dimensions :thumb))
custom-color (if (= type :danger) :danger customization-color)]
(rn/use-effect (fn []
(when @sliding-complete?
(on-complete)))
[@sliding-complete?])
(rn/use-effect (fn []
(when on-reset
(reset! sliding-complete? false)
(reset! gestures-disabled? false)
(animations/reset-track-position x-pos)
(on-reset)))
[on-reset])
[gesture/gesture-detector
{:gesture (animations/drag-gesture x-pos
gestures-disabled?
disabled?
(dimensions :usable-track)
sliding-complete?)}
[reanimated/view
{:test-ID :slide-button-track
:style (merge (style/track {:disabled? disabled?
:customization-color custom-color
:height (dimensions :track-height)
:blur? blur?})
container-style)
:on-layout (when-not (some? @track-width)
on-track-layout)}
[reanimated/view {:style (style/track-cover interpolate-track)}
[rn/view {:style (style/track-cover-text-container @track-width)}
[icon/icon track-icon
{:color (utils/text-color custom-color theme blur?)
:size 20}]
[rn/view {:width 4}]
[text/text
{:weight :medium
:size :paragraph-1
:style (style/track-text custom-color theme blur?)}
track-text]]]
[reanimated/view
{:style (style/thumb-container {:interpolate-track interpolate-track
:thumb-size (dimensions :thumb)
:customization-color custom-color
:theme theme
:blur? blur?})}
[reanimated/view {:style (style/arrow-icon-container interpolate-track)}
[icon/icon :arrow-right
{:color colors/white
:size 20}]]
[reanimated/view
{:style (style/action-icon interpolate-track
(dimensions :thumb))}
[icon/icon track-icon
{:color colors/white
:size 20}]]]]]))))
(defn- view-internal (defn view
"Options "Options
- `on-complete` Callback called when the sliding is complete - `on-complete` Callback called when the sliding is complete, returns reset fn as a parameter
- `disabled?` Boolean that disables the button - `disabled?` Boolean that disables the button
(_and gestures_) (_and gestures_)
- `size` :size/s-40`/`:size/s-48` - `size` :size/s-40`/`:size/s-48`
@ -106,9 +47,78 @@
- `track-icon` Key of the icon shown on the track - `track-icon` Key of the icon shown on the track
(e.g. `:face-id`) (e.g. `:face-id`)
- `customization-color` Customization color - `customization-color` Customization color
- `on-reset` A callback which can be used to reset the component and run required functionality
" "
[props] [{:keys [on-complete track-text track-icon disabled? customization-color size
[:f> f-slider props]) container-style type blur?]}]
(let [theme (quo.theme/use-theme-value)
(def view (quo.theme/with-theme view-internal)) x-pos (reanimated/use-shared-value 0)
[track-width set-track-width] (rn/use-state nil)
[sliding-complete?
set-sliding-complete] (rn/use-state false)
[gestures-disabled?
set-gestures-disabled] (rn/use-state disabled?)
on-track-layout (rn/use-callback
#(set-track-width (oops/oget % "nativeEvent.layout.width")))
reset-fn (rn/use-callback
(fn []
(set-sliding-complete false)
(set-gestures-disabled false)
(animations/reset-track-position x-pos)))
dimensions (rn/use-callback
(partial utils/get-dimensions
(or track-width constants/default-width)
size)
[track-width])
interpolate-track (rn/use-callback
(partial animations/interpolate-track
x-pos
(dimensions :usable-track)
(dimensions :thumb))
[dimensions])
custom-color (if (= type :danger) :danger customization-color)
gesture (rn/use-memo #(drag-gesture x-pos
gestures-disabled?
set-gestures-disabled
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn)
[gestures-disabled? sliding-complete? disabled?])]
[gesture/gesture-detector
{:gesture gesture}
[reanimated/view
{:test-ID :slide-button-track
:style (merge (style/track {:disabled? disabled?
:customization-color custom-color
:height (dimensions :track-height)
:blur? blur?})
container-style)
:on-layout on-track-layout}
[reanimated/view {:style (style/track-cover interpolate-track)}
[rn/view {:style (style/track-cover-text-container track-width)}
[icon/icon track-icon
{:color (utils/text-color custom-color theme blur?)
:size 20}]
[rn/view {:width 4}]
[text/text
{:weight :medium
:size :paragraph-1
:style (style/track-text custom-color theme blur?)}
track-text]]]
[reanimated/view
{:style (style/thumb-container {:interpolate-track interpolate-track
:thumb-size (dimensions :thumb)
:customization-color custom-color
:theme theme
:blur? blur?})}
[reanimated/view {:style (style/arrow-icon-container interpolate-track)}
[icon/icon :arrow-right
{:color colors/white
:size 20}]]
[reanimated/view
{:style (style/action-icon interpolate-track (dimensions :thumb))}
[icon/icon track-icon
{:color colors/white
:size 20}]]]]]))

View File

@ -4,26 +4,24 @@
[quo.components.icon :as quo.icons] [quo.components.icon :as quo.icons]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as theme] [quo.theme :as theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- view-internal (defn view
[] [{:keys [on-press on-long-press disabled? icon accessibility-label container-style]}]
(let [pressed? (reagent/atom false)] (let [theme (theme/use-theme-value)
(fn [pressed? set-pressed] (rn/use-state false)
[{:keys [on-press on-long-press disabled? icon accessibility-label container-style theme]}] on-press-in (rn/use-callback #(set-pressed true))
[rn/pressable on-press-out (rn/use-callback #(set-pressed nil))]
{:accessibility-label (or accessibility-label :wallet-button) [rn/pressable
:on-press on-press {:accessibility-label (or accessibility-label :wallet-button)
:on-press-in #(reset! pressed? true) :on-press on-press
:on-press-out #(reset! pressed? nil) :on-press-in on-press-in
:on-long-press on-long-press :on-press-out on-press-out
:disabled disabled? :on-long-press on-long-press
:style (merge (style/main {:pressed? @pressed? :disabled disabled?
:theme theme :style (merge (style/main {:pressed? pressed?
:disabled? disabled?}) :theme theme
container-style)} :disabled? disabled?})
[quo.icons/icon icon container-style)}
{:color (colors/theme-colors colors/neutral-100 colors/white theme)}]]))) [quo.icons/icon icon
{:color (colors/theme-colors colors/neutral-100 colors/white theme)}]]))
(def view (theme/with-theme view-internal))

View File

@ -9,7 +9,6 @@
[react-native.gesture :as gesture] [react-native.gesture :as gesture]
[react-native.hooks :as hooks] [react-native.hooks :as hooks]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im.common.bottom-sheet.style :as style] [status-im.common.bottom-sheet.style :as style]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -57,83 +56,77 @@
(show translate-y bg-opacity) (show translate-y bg-opacity)
(hide translate-y bg-opacity window-height on-close)))))) (hide translate-y bg-opacity window-height on-close))))))
(defn- f-view (defn view
[_ _] [{:keys [hide? insets]}
(let [sheet-height (reagent/atom 0) {:keys [content selected-item padding-bottom-override border-radius on-close shell?
item-height (reagent/atom 0)] gradient-cover? customization-color hide-handle? blur-radius]
(fn [{:keys [hide? insets theme]} :or {border-radius 12}}]
{:keys [content selected-item padding-bottom-override border-radius on-close shell? (let [theme (quo.theme/use-theme-value)
gradient-cover? customization-color hide-handle? blur-radius] sheet-height (rn/use-ref-atom 0)
:or {border-radius 12}}] item-height (rn/use-ref-atom 0)
(let [{window-height :height} (rn/get-window) {window-height :height} (rn/get-window)
bg-opacity (reanimated/use-shared-value 0) bg-opacity (reanimated/use-shared-value 0)
translate-y (reanimated/use-shared-value window-height) translate-y (reanimated/use-shared-value window-height)
sheet-gesture (get-sheet-gesture translate-y sheet-gesture (get-sheet-gesture translate-y
bg-opacity bg-opacity
window-height window-height
on-close) on-close)
selected-item-smaller-than-sheet? (< @item-height selected-item-smaller-than-sheet? (< @item-height
(- window-height (- window-height
@sheet-height @sheet-height
(:top insets) (:top insets)
(:bottom insets) (:bottom insets)
bottom-margin)) bottom-margin))
top (- window-height (:top insets) @sheet-height) top (- window-height (:top insets) @sheet-height)
bottom (if selected-item-smaller-than-sheet? bottom (if selected-item-smaller-than-sheet?
(+ @sheet-height bottom-margin) (+ @sheet-height bottom-margin)
(:bottom insets))] (:bottom insets))]
(rn/use-effect (rn/use-effect
#(if hide? #(if hide?
(hide translate-y bg-opacity window-height on-close) (hide translate-y bg-opacity window-height on-close)
(show translate-y bg-opacity)) (show translate-y bg-opacity))
[hide?]) [hide?])
(hooks/use-back-handler (fn [] (hooks/use-back-handler (fn []
(when (fn? on-close) (when (fn? on-close)
(on-close)) (on-close))
(rf/dispatch [:hide-bottom-sheet]) (rf/dispatch [:hide-bottom-sheet])
true)) true))
[rn/view {:style {:flex 1}} [rn/view {:style {:flex 1}}
;; backdrop ;; backdrop
[rn/pressable [rn/pressable
{:on-press #(rf/dispatch [:hide-bottom-sheet]) {:on-press #(rf/dispatch [:hide-bottom-sheet])
:style {:flex 1}} :style {:flex 1}}
[reanimated/view [reanimated/view
{:style (reanimated/apply-animations-to-style {:style (reanimated/apply-animations-to-style
{:opacity bg-opacity} {:opacity bg-opacity}
{:flex 1 :background-color colors/neutral-100-opa-70})}]] {:flex 1 :background-color colors/neutral-100-opa-70})}]]
;; sheet ;; sheet
[gesture/gesture-detector {:gesture sheet-gesture} [gesture/gesture-detector {:gesture sheet-gesture}
[reanimated/view [reanimated/view
{:style (reanimated/apply-animations-to-style {:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]} {:transform [{:translateY translate-y}]}
(style/sheet insets window-height selected-item))} (style/sheet insets window-height selected-item))}
(when shell? (when shell?
[blur/ios-view [blur/ios-view
{:style style/shell-bg {:style style/shell-bg
:blur-radius (or blur-radius 20) :blur-radius (or blur-radius 20)
:blur-type :transparent :blur-type :transparent
:overlay-color :transparent}]) :overlay-color :transparent}])
(when selected-item (when selected-item
[rn/view [rn/view
{:on-layout #(reset! item-height (.-nativeEvent.layout.height ^js %)) {:on-layout #(reset! item-height (.-nativeEvent.layout.height ^js %))
:style :style
(style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)} (style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)}
[selected-item]]) [selected-item]])
[rn/view [rn/view
{:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin) {:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin)
:on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))} :on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))}
(when (and gradient-cover? customization-color) (when (and gradient-cover? customization-color)
[rn/view {:style style/gradient-bg} [rn/view {:style style/gradient-bg}
[quo/gradient-cover [quo/gradient-cover
{:customization-color customization-color {:customization-color customization-color
:opacity 0.4}]]) :opacity 0.4}]])
(when-not hide-handle? (when-not hide-handle?
[quo/drawer-bar]) [quo/drawer-bar])
[content]]]]])))) [content]]]]]))
(defn- internal-view
[args sheet]
[:f> f-view args sheet])
(def view (quo.theme/with-theme internal-view))

View File

@ -3,45 +3,32 @@
[quo.core :as quo] [quo.core :as quo]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent]
[status-im.common.standard-authentication.standard-auth.authorize :as authorize] [status-im.common.standard-authentication.standard-auth.authorize :as authorize]
[status-im.constants :as constants] [status-im.constants :as constants]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn- view-internal (defn view
[_] [{:keys [track-text customization-color auth-button-label on-auth-success on-auth-fail
(let [reset-slider? (reagent/atom false) auth-button-icon-left size blur? container-style]
on-close (fn [] :or {container-style {:flex 1}}}]
(js/setTimeout (let [theme (quo.theme/use-theme-value)
#(reset! reset-slider? true)
200))
auth-method (rf/sub [:auth-method]) auth-method (rf/sub [:auth-method])
biometric-auth? (= auth-method constants/auth-method-biometric)] biometric-auth? (= auth-method constants/auth-method-biometric)
(fn [{:keys [track-text on-complete (rn/use-callback
customization-color (fn [reset]
auth-button-label (authorize/authorize {:on-close #(js/setTimeout reset 200)
on-auth-success :auth-button-icon-left auth-button-icon-left
on-auth-fail :theme theme
auth-button-icon-left :blur? blur?
size :biometric-auth? biometric-auth?
theme :on-auth-success on-auth-success
blur? :on-auth-fail on-auth-fail
container-style] :auth-button-label auth-button-label}))
:or {container-style {:flex 1}}}] [theme])]
[rn/view {:style container-style} [quo/slide-button
[quo/slide-button {:container-style container-style
{:size size :size size
:customization-color customization-color :customization-color customization-color
:on-reset (when @reset-slider? #(reset! reset-slider? false)) :on-complete on-complete
:on-complete #(authorize/authorize {:on-close on-close :track-icon (if biometric-auth? :i/face-id :password)
:auth-button-icon-left auth-button-icon-left :track-text track-text}]))
:theme theme
:blur? blur?
:biometric-auth? biometric-auth?
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
:auth-button-label auth-button-label})
:track-icon (if biometric-auth? :i/face-id :password)
:track-text track-text}]])))
(def view (quo.theme/with-theme view-internal))

View File

@ -48,7 +48,7 @@
:disabled? (:disabled? @state) :disabled? (:disabled? @state)
:blur? @blur? :blur? @blur?
:type (:type @state) :type (:type @state)
:on-complete (fn [] :on-complete (fn [_]
(js/setTimeout (fn [] (reset! complete? true)) (js/setTimeout (fn [] (reset! complete? true))
1000) 1000)
(js/alert "I don't wanna slide anymore"))}] (js/alert "I don't wanna slide anymore"))}]