feat: persistent send/receive action at bottom of asset list
When the account card is scrolled out of view a send/receive button group appears at the bottom of the asset list; uses native animation to raise and lower the button group into and out of view. Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
6aba34b82d
commit
00501f44b9
|
@ -42,6 +42,7 @@
|
||||||
:ValueXY (fn [])
|
:ValueXY (fn [])
|
||||||
:View {}
|
:View {}
|
||||||
:FlatList {}
|
:FlatList {}
|
||||||
|
:ScrollView {}
|
||||||
:Text {}}
|
:Text {}}
|
||||||
:Easing {:bezier (fn [])
|
:Easing {:bezier (fn [])
|
||||||
:poly (fn [])
|
:poly (fn [])
|
||||||
|
|
|
@ -68,9 +68,15 @@
|
||||||
(def animated-flat-list-class
|
(def animated-flat-list-class
|
||||||
(reagent/adapt-react-class (.-FlatList ^js animated)))
|
(reagent/adapt-react-class (.-FlatList ^js animated)))
|
||||||
|
|
||||||
|
(def animated-scroll-view-class
|
||||||
|
(reagent/adapt-react-class (.-ScrollView ^js animated)))
|
||||||
|
|
||||||
(defn animated-view [props & content]
|
(defn animated-view [props & content]
|
||||||
(vec (conj content props animated-view-class)))
|
(vec (conj content props animated-view-class)))
|
||||||
|
|
||||||
|
(defn animated-scroll-view [props & children]
|
||||||
|
(vec (conj children props animated-scroll-view-class)))
|
||||||
|
|
||||||
(def dimensions (.-Dimensions react-native))
|
(def dimensions (.-Dimensions react-native))
|
||||||
(def keyboard (.-Keyboard react-native))
|
(def keyboard (.-Keyboard react-native))
|
||||||
(def dismiss-keyboard! #(.dismiss ^js Keyboard))
|
(def dismiss-keyboard! #(.dismiss ^js Keyboard))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.ui.screens.wallet.account.styles
|
(ns status-im.ui.screens.wallet.account.styles
|
||||||
(:require [status-im.ui.components.colors :as colors]))
|
(:require [status-im.ui.components.colors :as colors]
|
||||||
|
[status-im.ui.components.animation :as animation]))
|
||||||
|
|
||||||
(defn card [window-width color]
|
(defn card [window-width color]
|
||||||
{:width (- window-width 30)
|
{:width (- window-width 30)
|
||||||
|
@ -24,4 +25,20 @@
|
||||||
:shadow-opacity 1
|
:shadow-opacity 1
|
||||||
:shadow-color (if (colors/dark?)
|
:shadow-color (if (colors/dark?)
|
||||||
"rgba(0, 0, 0, 0.75)"
|
"rgba(0, 0, 0, 0.75)"
|
||||||
"rgba(0, 9, 26, 0.12)")})
|
"rgba(0, 9, 26, 0.12)")})
|
||||||
|
|
||||||
|
(defn bottom-send-recv-buttons-raise [anim-y]
|
||||||
|
(animation/timing
|
||||||
|
anim-y
|
||||||
|
{:toValue 0
|
||||||
|
:duration 200
|
||||||
|
:easing (.-ease ^js (animation/easing))
|
||||||
|
:useNativeDriver true}))
|
||||||
|
|
||||||
|
(defn bottom-send-recv-buttons-lower [anim-y y]
|
||||||
|
(animation/timing
|
||||||
|
anim-y
|
||||||
|
{:toValue y
|
||||||
|
:duration 200
|
||||||
|
:easing (.-ease ^js (animation/easing))
|
||||||
|
:useNativeDriver true}))
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
[status-im.ui.components.list-item.views :as list-item]
|
[status-im.ui.components.list-item.views :as list-item]
|
||||||
[status-im.utils.money :as money]
|
[status-im.utils.money :as money]
|
||||||
[status-im.wallet.utils :as wallet.utils]
|
[status-im.wallet.utils :as wallet.utils]
|
||||||
[status-im.ui.components.topbar :as topbar]))
|
[status-im.ui.components.topbar :as topbar]
|
||||||
|
[status-im.ui.components.animation :as animation]))
|
||||||
|
|
||||||
(def state (reagent/atom {:tab :assets}))
|
(def state (reagent/atom {:tab :assets}))
|
||||||
|
|
||||||
|
@ -28,12 +29,14 @@
|
||||||
{:content sheets/account-settings
|
{:content sheets/account-settings
|
||||||
:content-height 60}])}]}])
|
:content-height 60}])}]}])
|
||||||
|
|
||||||
(defn button [label icon handler]
|
(defn button [label icon color handler]
|
||||||
[react/touchable-highlight {:on-press handler :style {:flex 1}}
|
[react/touchable-highlight {:on-press handler :style {:flex 1}}
|
||||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||||
[react/view {:flex-direction :row :align-items :center}
|
[react/view {:flex-direction :row :align-items :center}
|
||||||
[icons/icon icon {:color colors/white-persist}]
|
[icons/icon icon {:color color}]
|
||||||
[react/text {:style {:margin-left 8 :color colors/white-persist}} label]]]])
|
[react/text {:style {:margin-left 8 :color color}} label]]]])
|
||||||
|
|
||||||
|
(def button-group-height 52)
|
||||||
|
|
||||||
(views/defview account-card [{:keys [address color type] :as account}]
|
(views/defview account-card [{:keys [address color type] :as account}]
|
||||||
(views/letsubs [currency [:wallet/currency]
|
(views/letsubs [currency [:wallet/currency]
|
||||||
|
@ -57,7 +60,7 @@
|
||||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:show-popover {:view :share-account :address address}])}
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:show-popover {:view :share-account :address address}])}
|
||||||
[icons/icon :main-icons/share {:color colors/white-persist
|
[icons/icon :main-icons/share {:color colors/white-persist
|
||||||
:accessibility-label :share-wallet-address-icon}]]]
|
:accessibility-label :share-wallet-address-icon}]]]
|
||||||
[react/view {:height 52 :background-color colors/black-transparent-20
|
[react/view {:height button-group-height :background-color colors/black-transparent-20
|
||||||
:border-bottom-right-radius 8 :border-bottom-left-radius 8 :flex-direction :row}
|
:border-bottom-right-radius 8 :border-bottom-left-radius 8 :flex-direction :row}
|
||||||
(if (= type :watch)
|
(if (= type :watch)
|
||||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||||
|
@ -66,11 +69,13 @@
|
||||||
[button
|
[button
|
||||||
(i18n/label :t/wallet-send)
|
(i18n/label :t/wallet-send)
|
||||||
:main-icons/send
|
:main-icons/send
|
||||||
|
colors/white-persist
|
||||||
#(re-frame/dispatch [:wallet/prepare-transaction-from-wallet account])])
|
#(re-frame/dispatch [:wallet/prepare-transaction-from-wallet account])])
|
||||||
[react/view {:style (styles/divider)}]
|
[react/view {:style (styles/divider)}]
|
||||||
[button
|
[button
|
||||||
(i18n/label :t/receive)
|
(i18n/label :t/receive)
|
||||||
:main-icons/receive
|
:main-icons/receive
|
||||||
|
colors/white-persist
|
||||||
#(re-frame/dispatch [:show-popover {:view :share-account :address address}])]]]))
|
#(re-frame/dispatch [:show-popover {:view :share-account :address address}])]]]))
|
||||||
|
|
||||||
(defn render-collectible [address]
|
(defn render-collectible [address]
|
||||||
|
@ -119,13 +124,65 @@
|
||||||
(= tab :history)
|
(= tab :history)
|
||||||
[transactions address])])))
|
[transactions address])])))
|
||||||
|
|
||||||
|
(views/defview bottom-send-recv-buttons [{:keys [address type] :as account} anim-y]
|
||||||
|
[react/animated-view {:style {:background-color colors/white
|
||||||
|
:bottom 0
|
||||||
|
:flex-direction :row
|
||||||
|
:height button-group-height
|
||||||
|
:position :absolute
|
||||||
|
:shadow-offset {:width 0 :height 1}
|
||||||
|
:shadow-opacity 0.75
|
||||||
|
:shadow-radius 1
|
||||||
|
:transform [{:translateY anim-y}]
|
||||||
|
:width "100%"}}
|
||||||
|
(if (= type :watch)
|
||||||
|
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||||
|
[react/text {:style {:margin-left 8 :color colors/blue-persist}}
|
||||||
|
(i18n/label :t/watch-only)]]
|
||||||
|
[button
|
||||||
|
(i18n/label :t/wallet-send)
|
||||||
|
:main-icons/send
|
||||||
|
colors/blue-persist
|
||||||
|
#(re-frame/dispatch [:wallet/prepare-transaction-from-wallet account])])
|
||||||
|
[button
|
||||||
|
(i18n/label :t/receive)
|
||||||
|
:main-icons/receive
|
||||||
|
colors/blue-persist
|
||||||
|
#(re-frame/dispatch [:show-popover {:view :share-account :address address}])]])
|
||||||
|
|
||||||
|
(defn anim-listener [anim-y scroll-y]
|
||||||
|
(let [to-show (atom false)]
|
||||||
|
(animation/add-listener
|
||||||
|
scroll-y
|
||||||
|
(fn [anim]
|
||||||
|
(let [y-trigger 149]
|
||||||
|
(cond
|
||||||
|
(and (>= (.-value anim) y-trigger) (not @to-show))
|
||||||
|
(animation/start
|
||||||
|
(styles/bottom-send-recv-buttons-raise anim-y)
|
||||||
|
#(reset! to-show true))
|
||||||
|
|
||||||
|
(and (< (.-value anim) y-trigger) @to-show)
|
||||||
|
(animation/start
|
||||||
|
(styles/bottom-send-recv-buttons-lower anim-y button-group-height)
|
||||||
|
#(reset! to-show false))))))))
|
||||||
|
|
||||||
(views/defview account []
|
(views/defview account []
|
||||||
(views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account]]
|
(views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account]]
|
||||||
[react/view {:flex 1 :background-color colors/white}
|
(let [anim-y (animation/create-value button-group-height)
|
||||||
[toolbar-view name]
|
scroll-y (animation/create-value 0)]
|
||||||
[react/scroll-view
|
(anim-listener anim-y scroll-y)
|
||||||
[react/view {:padding-left 16}
|
[react/view {:flex 1 :background-color colors/white}
|
||||||
[react/scroll-view {:horizontal true}
|
[toolbar-view name]
|
||||||
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
|
[react/animated-scroll-view
|
||||||
[account-card account]]]]
|
{:contentContainerStyle {:padding-bottom button-group-height}
|
||||||
[assets-and-collections address]]]))
|
:on-scroll (animation/event
|
||||||
|
[{:nativeEvent {:contentOffset {:y scroll-y}}}]
|
||||||
|
{:useNativeDriver true})
|
||||||
|
:scrollEventThrottle 1}
|
||||||
|
[react/view {:padding-left 16}
|
||||||
|
[react/scroll-view {:horizontal true}
|
||||||
|
[react/view {:flex-direction :row :padding-top 8 :padding-bottom 12}
|
||||||
|
[account-card account]]]]
|
||||||
|
[assets-and-collections address]]
|
||||||
|
[bottom-send-recv-buttons account anim-y]])))
|
||||||
|
|
Loading…
Reference in New Issue