Skip to content

Commit

Permalink
Rework bottom-sheet component
Browse files Browse the repository at this point in the history
Fixes #9848
  • Loading branch information
Ferossgp committed Jan 25, 2020
1 parent 8571e7a commit b799998
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 165 deletions.
10 changes: 6 additions & 4 deletions src/status_im/ui/components/bottom_sheet/styles.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

(def border-radius 16)
(def bottom-padding (if platform/iphone-x? 34 8))
(def bottom-view-height 1000)
(def top-padding 8)
(def bottom-view-height 1000) ; should be window-height

(def container
{:position :absolute
Expand Down Expand Up @@ -33,9 +34,10 @@
:height (+ content-height bottom-view-height)
:bottom (- bottom-view-height)
:align-self :stretch
:transform [{:translateY bottom-value}]
:justify-content :flex-start
:padding-bottom bottom-padding})
:transform [{:translateY bottom-value}]})

(def sheet-wrapper {:flex 1
:justify-content :flex-end})

(def content-header
{:height border-radius
Expand Down
171 changes: 82 additions & 89 deletions src/status_im/ui/components/bottom_sheet/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
(def release-animation-duration 150)
(def cancellation-animation-duration 100)
(def swipe-opacity-range 100)
(def cancellation-height 180)
(def cancellation-coefficient 0.3)
(def min-opacity 0.05)
(def min-velocity 0.1)

Expand All @@ -31,13 +31,6 @@
:useNativeDriver true})])
(when (fn? callback) callback)))

(defn animate-panel-open [opacity-value bottom-value]
(animate {:bottom bottom-value
:new-bottom-value 0
:opacity opacity-value
:new-opacity-value 1
:duration initial-animation-duration}))

(defn- on-move
[{:keys [height bottom-value opacity-value]}]
(fn [_ state]
Expand All @@ -49,35 +42,24 @@
(neg? dy)
(animation/set-value bottom-value (/ dy 2))))))

(defn cancelled? [height dy vy]
(defn- cancelled? [height dy vy]
(or
(<= min-velocity vy)
(> cancellation-height (- height dy))))

(defn- cancel
([opts] (cancel opts nil))
([{:keys [height bottom-value show-sheet? opacity-value]} callback]
(animate {:bottom bottom-value
:new-bottom-value height
:opacity opacity-value
:new-opacity-value 0
:duration cancellation-animation-duration
:callback #(do (reset! show-sheet? false)
(when (fn? callback) (callback)))})))
(> (* cancellation-coefficient height) (- height dy))))

(defn- on-release
[{:keys [height bottom-value opacity-value on-cancel] :as opts}]
[{:keys [height bottom-value close-sheet opacity-value] :as opts}]
(fn [_ state]
(let [{:strs [dy vy]} (js->clj state)]
(if (cancelled? height dy vy)
(cancel opts on-cancel)
(close-sheet)
(animate {:bottom bottom-value
:new-bottom-value 0
:opacity opacity-value
:new-opacity-value 1
:duration release-animation-duration})))))

(defn swipe-pan-responder [opts]
(defn- swipe-pan-responder [opts]
(.create
react/pan-responder
(clj->js
Expand All @@ -88,73 +70,84 @@
:onPanResponderRelease (on-release opts)
:onPanResponderTerminate (on-release opts)})))

(defn pan-handlers [pan-responder]
(defn- pan-handlers [pan-responder]
(js->clj (.-panHandlers pan-responder)))

(defn- bottom-sheet-view
[{:keys [opacity-value bottom-value]}]
(reagent.core/create-class
{:component-did-mount
#(animate-panel-open opacity-value bottom-value)
:reagent-render
(fn [{:keys [opacity-value bottom-value height
content on-cancel disable-drag?]
:or {on-cancel #(re-frame/dispatch [:bottom-sheet/hide])}
:as opts}]
[react/keyboard-avoiding-view {:style styles/container}
[react/touchable-highlight
{:on-press #(cancel opts on-cancel)
:style styles/container}
(defn- on-open [{:keys [bottom-value opacity-value height internal-visible]}]
(reset! internal-visible true)
(animate {:bottom bottom-value
:new-bottom-value 0
:opacity opacity-value
:new-opacity-value 1
:duration initial-animation-duration}))

[react/animated-view (styles/shadow opacity-value)]]
[react/animated-view (merge
{:style (styles/content-container height bottom-value)}
(when-not disable-drag?
(pan-handlers (swipe-pan-responder opts))))
[react/view {:style styles/content-header}
[react/view styles/handle]]
[react/view {:style {:flex 1
:height height}}
[content]]
[react/view {:style styles/bottom-view}]]])}))
(defn- on-close
[{:keys [bottom-value opacity-value on-cancel height
internal-visible with-callback?]}]
(animate {:bottom bottom-value
:new-bottom-value height
:opacity opacity-value
:new-opacity-value 0
:duration cancellation-animation-duration
:callback (fn []
(reset! internal-visible false)
(reagent/flush)
(when (fn? on-cancel)
(on-cancel)))}))

(defn bottom-sheet
[{:keys [show? content-height on-cancel]}]
(let [show-sheet? (reagent/atom show?)
total-content-height (+ content-height styles/border-radius
styles/bottom-padding)
bottom-value (animation/create-value total-content-height)
opacity-value (animation/create-value 0)
opts {:height total-content-height
:bottom-value bottom-value
:opacity-value opacity-value
:show-sheet? show-sheet?
:on-cancel on-cancel}]
(reagent.core/create-class
{:component-will-update
(fn [this [_ new-args]]
(let [old-args (second (.-argv (.-props this)))
old-show? (:show? old-args)
new-show? (:show? new-args)
old-height (:content-height old-args)
new-height (:content-height new-args)
total-content-height (+ new-height
styles/border-radius
styles/bottom-padding)
opts' (assoc opts :height total-content-height)]
(when (and new-show? (not= old-height new-height))
(animation/set-value bottom-value new-height))
(cond (and (not old-show?) new-show?)
(reset! show-sheet? true)
;; TODO: Replace with modal, firtstly should convert also popover
;; NOTE: onRequestClose of modal should close sheet
;; TODO: animate content-height change
;; TODO: add max-height
(defn bottom-sheet []
(let [opacity-value (animation/create-value 0)
bottom-value (animation/create-value 0)
content-height (reagent/atom 200) ; TODO: add a defualt value (half of screen height?) to have better init animation
internal-visible (reagent/atom nil)
external-visible (reagent/atom nil)]
(fn [{:keys [content on-cancel disable-drag? show?]
:or {on-cancel #(re-frame/dispatch [:bottom-sheet/hide])}
:as opts}]
(let [height (+ @content-height
styles/border-radius
styles/bottom-padding
styles/top-padding)
close-sheet (fn []
(on-close {:opacity-value opacity-value
:bottom-value bottom-value
:height height
:internal-visible internal-visible
:on-cancel on-cancel}))]
(when-not (= @external-visible show?)
(reset! external-visible show?)
(if show?
(on-open {:bottom-value bottom-value
:opacity-value opacity-value
:height height
:internal-visible internal-visible})
(close-sheet)))
(when @internal-visible
[react/view {:style styles/container}
[react/touchable-highlight {:style styles/container
:on-press #(close-sheet)}
[react/animated-view {:style (styles/shadow opacity-value)}]]

(and old-show? (false? new-show?) (true? @show-sheet?))
(cancel opts'))))
:reagent-render
(fn [{:keys [content content-height]}]
(let [total-content-height (+ content-height
styles/border-radius
styles/bottom-padding)]
(when @show-sheet?
[bottom-sheet-view (assoc opts
:content content
:height total-content-height)])))})))
[react/keyboard-avoiding-view {:pointer-events "box-none"
:style styles/sheet-wrapper}
[react/animated-view (merge
{:pointer-events "box-none"
:style (styles/content-container height bottom-value)}
(when-not disable-drag?
(pan-handlers
(swipe-pan-responder {:bottom-value bottom-value
:opacity-value opacity-value
:height height
:close-sheet #(close-sheet)}))))
[react/view {:style styles/content-header}
[react/view styles/handle]]
[react/view {:on-layout #(->> %
.-nativeEvent
.-layout
.-height
(reset! content-height))}
[content]]]]])))))
60 changes: 29 additions & 31 deletions src/status_im/ui/screens/home/sheet/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,34 @@
(re-frame/dispatch event))

(defn add-new-view []
[react/view {:flex 1 :flex-direction :row}
[react/view {:flex 1}
[list-item/list-item
{:theme :action
:title :t/start-new-chat
:accessibility-label :start-1-1-chat-button
:icon :main-icons/one-on-one-chat
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-chat])}]
(when config/group-chat-enabled?
[list-item/list-item
{:theme :action
:title :t/start-group-chat
:accessibility-label :start-group-chat-button
:icon :main-icons/group-chat
:on-press #(hide-sheet-and-dispatch [:contact.ui/start-group-chat-pressed])}])
[list-item/list-item
{:theme :action
:title :t/new-public-group-chat
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-public-chat])}]
[list-item/list-item
{:theme :action
:title :t/invite-friends
:accessibility-label :chats-menu-invite-friends-button
:icon :main-icons/share
:on-press #(do
(re-frame/dispatch [:bottom-sheet/hide-sheet])
(list-selection/open-share {:message (i18n/label :t/get-status-at)}))}]]])
[react/view
[list-item/list-item
{:theme :action
:title :t/start-new-chat
:accessibility-label :start-1-1-chat-button
:icon :main-icons/one-on-one-chat
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-chat])}]
(when config/group-chat-enabled?
[list-item/list-item
{:theme :action
:title :t/start-group-chat
:accessibility-label :start-group-chat-button
:icon :main-icons/group-chat
:on-press #(hide-sheet-and-dispatch [:contact.ui/start-group-chat-pressed])}])
[list-item/list-item
{:theme :action
:title :t/new-public-group-chat
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-public-chat])}]
[list-item/list-item
{:theme :action
:title :t/invite-friends
:accessibility-label :chats-menu-invite-friends-button
:icon :main-icons/share
:on-press #(do
(re-frame/dispatch [:bottom-sheet/hide-sheet])
(list-selection/open-share {:message (i18n/label :t/get-status-at)}))}]])

(def add-new
{:content add-new-view
:content-height (if config/group-chat-enabled? 256 192)})
{:content add-new-view})
68 changes: 27 additions & 41 deletions src/status_im/ui/screens/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,33 @@

(defonce initial-view-id (atom nil))

(defn bottom-sheet-comp [opts height-atom]
;; We compute bottom sheet height dynamically by rendering it
;; on an invisible view; then, if height is already available
;; (either because it is statically provided or computed),
;; we render the sheet itself
(if (or (not @height-atom) (= 0 @height-atom))
[react/view {:style {:position :absolute :opacity 0}
:on-layout (fn [e]
(let [h (-> e .-nativeEvent .-layout .-height)]
(reset! height-atom h)))}
(when (:content opts)
[(:content opts)])]
[bottom-sheet/bottom-sheet (assoc opts :content-height @height-atom)]))

(views/defview bottom-sheet []
(views/letsubs [{:keys [show? view]} [:bottom-sheet]]
(let [opts (cond-> {:show? show?
:on-cancel #(re-frame/dispatch [:bottom-sheet/hide])}

(map? view)
(merge view)

(= view :mobile-network)
(merge mobile-network-settings/settings-sheet)

(= view :mobile-network-offline)
(merge mobile-network-settings/offline-sheet)

(= view :add-new)
(merge home.sheet/add-new)

(= view :keycard.login/more)
(merge keycard/more-sheet)

(= view :learn-more)
(merge about-app/learn-more)

(= view :recover-sheet)
(merge (recover.views/bottom-sheet)))
height-atom (reagent/atom (if (:content-height opts) (:content-height opts) nil))]
[bottom-sheet-comp opts height-atom])))
(defn bottom-sheet []
(fn []
(let [{:keys [show? view]} @(re-frame/subscribe [:bottom-sheet])
opts (cond-> {:show? show?
:on-cancel #(re-frame/dispatch [:bottom-sheet/hide])}

(map? view)
(merge view)

(= view :mobile-network)
(merge mobile-network-settings/settings-sheet)

(= view :mobile-network-offline)
(merge mobile-network-settings/offline-sheet)

(= view :add-new)
(merge home.sheet/add-new)

(= view :keycard.login/more)
(merge keycard/more-sheet)

(= view :learn-more)
(merge about-app/learn-more)

(= view :recover-sheet)
(merge (recover.views/bottom-sheet)))]
[bottom-sheet/bottom-sheet opts])))

(defn reset-component-on-mount [view-id component two-pane?]
(when (and @initial-view-id
Expand Down

0 comments on commit b799998

Please sign in to comment.