From da535c025b7604d6b094d7ddd0b12b34ddc53c47 Mon Sep 17 00:00:00 2001 From: Adrian Tiberius Date: Mon, 9 May 2016 21:22:02 +0300 Subject: [PATCH] refactored carousel component Former-commit-id: d68e0781302955b605bdd1141e7f092038c0a92e --- src/syng_im/components/carousel.cljs | 150 --------------- src/syng_im/components/carousel/carousel.cljs | 178 ++++++++++++++++++ src/syng_im/components/carousel/styles.cljs | 24 +++ .../discovery/discovery_popular.cljs | 3 +- .../discovery/discovery_popular_list.cljs | 13 +- .../discovery_popular_list_item.cljs | 1 - src/syng_im/components/discovery/styles.cljs | 4 +- 7 files changed, 211 insertions(+), 162 deletions(-) delete mode 100644 src/syng_im/components/carousel.cljs create mode 100644 src/syng_im/components/carousel/carousel.cljs create mode 100644 src/syng_im/components/carousel/styles.cljs diff --git a/src/syng_im/components/carousel.cljs b/src/syng_im/components/carousel.cljs deleted file mode 100644 index 5c5904f0f0..0000000000 --- a/src/syng_im/components/carousel.cljs +++ /dev/null @@ -1,150 +0,0 @@ -(ns syng-im.components.carousel - (:require [syng-im.components.react :refer [android? - view - scroll-view - touchable-without-feedback - text]] - [syng-im.utils.logging :as log])) - - -(defn page-width [] - (.-width (.get (.. js/React -Dimensions) "window"))) - -(def defaults {:gap 10 - :sneak 10 - :pageWidth (- (page-width) 40) - :scrollThreshold 20}) - - -(defn get-gap [data] - (get data :gap (:gap defaults))) - -(defn get-sneak [data] - (get data :sneak (:sneak defaults))) - -(defn get-page-width [data] - (get data :pageWidth (:pageWidth defaults))) - -(defn get-scroll-threshold [data] - (get data :scrollThreshold (:scrollThreshold defaults))) - -(defn calculate-gap [component props] - (let [prop-page-width (get-page-width props) - page-width (page-width) - sneak (get-sneak props) - gap (quot (- (- page-width (* 2 sneak)) prop-page-width) 2)] - (log/debug "calculate-gap: prop-page-width=" prop-page-width - "; page-width=" page-width"; sneak=" sneak "; gap=" gap) - (when (> prop-page-width page-width) - (log/warn "Invalid pageWidth")) - (reagent.core/set-state component {:gap gap}) - )) - -(defn scroll-to [component x y] - (.scrollTo (.-scrollView component) (clj->js {:y y - :x x}))) - -(defn get-current-position [event] - (.-x (.-contentOffset (.-nativeEvent event)))) - -(defn on-scroll-end [event component starting-position] - (let [props (reagent.core/props component) - state (reagent.core/state component) - prop-page-width (get-page-width props) - sneak (get-sneak props) - scroll-threshold (get-scroll-threshold props) - gap (get-gap state) - page-offset (+ prop-page-width gap) - current-position (get-current-position event) - direction (cond - (> current-position (+ starting-position scroll-threshold)) 1 - (< current-position (- starting-position scroll-threshold)) -1 - :else 0) - current-page (+ (quot starting-position page-offset) direction) - ] - (log/debug "on-scroll-end: prop-page-width=" prop-page-width - "; sneak=" sneak "; gap=" gap "; page-offset=" page-offset - "; starting position=" starting-position - "; current-position=" current-position - "; direction=" direction "; current-page=" current-page) - (scroll-to component (* current-page page-offset) 0) - (reagent.core/set-state component {:activePage current-page}) - (when (:onPageChange props) - ((:onPageChange props) current-page)))) - -(defn go-to-page [component position] - (let [props (reagent.core/props component) - state (reagent.core/state component) - props-page-width (get-page-width props) - gap (get-gap state) - page-position (* position (+ props-page-width gap))] - (log/debug "go-to-page: props-page-width=" props-page-width "; gap=" gap - "; page-position=" page-position) - (scroll-to component page-position 0))) - -(defn component-will-mount [component new-args] - (let [props (reagent.core/props component)] - (log/debug "component-will-mount: component=" component "; new-args="new-args) - (calculate-gap component props))) - -(defn component-did-mount [component] - (let [props (reagent.core/props component) - initial-page (.-initialPage props)] - (log/debug "component-did-mount: initial-page="initial-page) - (when (pos? initial-page) - (go-to-page component initial-page)))) - -(defn component-will-receive-props [component new-argv] - (log/debug "component-will-receive-props: component=" component - "; new-argv=" new-argv) - (calculate-gap component new-argv)) - -(defn get-pages [component data children] - (let [props-page-width (get-page-width data) - page-style (get data :pageStyle {}) - gap (get-gap data) - margin (quot gap 2)] - (map-indexed (fn [index child] - (let [page-index index - touchable-data {:key index - :onPress (fn [event] - (go-to-page component page-index))}] - (log/debug "page " index " - " child) - [touchable-without-feedback touchable-data - [view {:style [{:width props-page-width - :justifyContent "center" - :marginLeft margin - :marginRight margin} - page-style]} - child]])) children))) - -(defn reagent-render [data children] - (let [starting-position (atom 0) - component (reagent.core/current-component) - sneak (get-sneak data) - gap (get-gap data) - pages (get-pages component data children)] - (log/debug "reagent-render: ") - [view {:style {:flex 1}} - [scroll-view {:contentContainerStyle {:paddingLeft (+ sneak (quot gap 2)) - :paddingRight (+ sneak (quot gap 2))} - :automaticallyAdjustContentInsets false - :bounces false - :decelerationRate 0.9 - :horizontal true - :onScrollBeginDrag #(reset! starting-position (get-current-position %)) - :onScrollEndDrag #(on-scroll-end % component @starting-position) - :showsHorizontalScrollIndicator false - :ref (fn [c] (set! (.-scrollView component) c)) - } - pages]] - )) - -(defn carousel [data children] - (let [component-data {:component-did-mount component-did-mount - :component-will-mount component-will-mount - :component-will-receive-props component-will-receive-props - :display-name "carousel" - :reagent-render reagent-render}] - (log/debug "Creating carousel component: " data children) - (reagent.core/create-class component-data))) diff --git a/src/syng_im/components/carousel/carousel.cljs b/src/syng_im/components/carousel/carousel.cljs new file mode 100644 index 0000000000..b489482f5d --- /dev/null +++ b/src/syng_im/components/carousel/carousel.cljs @@ -0,0 +1,178 @@ +(ns syng-im.components.carousel + (:require [syng-im.components.react :refer [android? + view + scroll-view + touchable-without-feedback + text]] + [syng-im.components.carousel.styles :as st] + [syng-im.utils.logging :as log])) + + +(defn window-page-width [] + (.-width (.get (.. js/React -Dimensions) "window"))) + +(def defaults {:gap 10 + :sneak 10 + :pageStyle {} + :scrollThreshold 20}) + +(defn get-active-page [data] + (get data :activePage 0)) + +(defn get-sneak [data] + (get data :sneak (:sneak defaults))) + +(defn get-gap [data] + (get data :gap (:gap defaults))) + +(defn compute-page-width + ([gap sneak] + (compute-page-width (window-page-width) gap sneak)) + ([window-page-width gap sneak] + (- window-page-width (+ (* 2 gap) (* 2 sneak))))) + +(defn get-page-width [data] + (get data :pageWidth (compute-page-width (get-gap data) (get-sneak data)))) + +(defn get-page-style [data] + (let [data-style (get data :pageStyle {})] + (merge (:pageStyle defaults) data-style))) + +(defn get-scroll-threshold [data] + (get data :scrollThreshold (:scrollThreshold defaults))) + +(defn apply-props [component props] + (let [sneak (get-sneak props) + page-width (get-page-width props) + style (get-page-style props) + gap (quot (- (- (window-page-width) (* 2 sneak)) page-width) 2)] + (reagent.core/set-state component {:sneak sneak + :pageWidth page-width + :pageStyle style + :gap gap}))) + +(defn scroll-to [component x y] + (.scrollTo (.-scrollView component) (clj->js {:y y + :x x}))) + +(defn get-current-position [event] + (.-x (.-contentOffset (.-nativeEvent event)))) + +(defn go-to-page [component page] + (let [props (reagent.core/props component) + state (reagent.core/state component) + page-width (get-page-width state) + gap (get-gap state) + page-position (* page (+ page-width gap))] + (log/debug "go-to-page: props-page-width=" page-width "; gap=" gap + "; page-position=" page-position) + (scroll-to component page-position 0) + (reagent.core/set-state component {:activePage page}) + (when (:onPageChange props) + ((:onPageChange props) page)))) + +(defn on-scroll-end [event component starting-position] + (let [props (reagent.core/props component) + state (reagent.core/state component) + scroll-threshold (get-scroll-threshold props) + current-page (get-active-page state) + current-position (get-current-position event) + direction (cond + (> current-position (+ starting-position scroll-threshold)) 1 + (< current-position (- starting-position scroll-threshold)) -1 + :else 0) + new-page (+ current-page direction) + ] + (log/debug state "on-scroll-end: starting position=" starting-position + "; current-position=" current-position "; direction=" direction + "; current-page=" current-page "; new-page=" new-page) + (if (not= current-page new-page) + (go-to-page component new-page) + (scroll-to component starting-position 0)))) + +(defn component-will-mount [component new-args] + (let [props (reagent.core/props component)] + (log/debug "component-will-mount: new-args="new-args) + (apply-props component props))) + +(defn component-did-mount [component] + (let [props (reagent.core/props component) + initial-page (.-initialPage props)] + (log/debug "component-did-mount: initial-page="initial-page) + (when (pos? initial-page) + (go-to-page component initial-page)))) + +(defn component-will-update [component new-argv] + (log/debug "component-will-update: ")) + +(defn component-did-update [component old-argv] + (log/debug "component-did-update")) + +(defn component-will-receive-props [component new-argv] + (log/debug "component-will-receive-props: new-argv=" new-argv) + (apply-props component new-argv)) + +(defn get-event-width [event] + (.-width (.-layout (.-nativeEvent event)))) + +(defn on-layout-change [event component] + (let [state (reagent.core/state component) + page-width (compute-page-width (get-event-width event) (get-gap state) (get-sneak state)) + state-page-width (get-page-width state) + active-page (get-active-page state) + gap (get-gap state) + page-position (* active-page (+ page-width gap))] + (log/debug "Layout changed: " " page-width=" page-width "; state-page-width=" state-page-width) + (if (not= page-width state-page-width) + (do + (reagent.core/set-state component {:pageWidth page-width}) + (.setState component {:layout (.-layout (.-nativeEvent event))}) + ) + (scroll-to component page-position 0)))) + +(defn get-pages [component data children] + (let [page-width (get-page-width data) + page-style (get-page-style data) + gap (get-gap data) + margin (quot gap 2)] + (doall (map-indexed (fn [index child] + (let [page-index index + touchable-data {:key index + :onPress #(go-to-page component page-index)}] + [touchable-without-feedback touchable-data + [view {:style [(st/page page-width margin) + page-style] + :onLayout #(log/debug "view onLayout" %)} + + child]])) children)))) + +(defn reagent-render [data children] + (let [starting-position (atom 0) + component (reagent.core/current-component) + state (reagent.core/state component) + sneak (get-sneak state) + gap (get-gap state)] + (log/debug "reagent-render: " data state) + [view {:style st/scroll-view-container} + [scroll-view {:contentContainerStyle (st/content-container sneak gap) + :automaticallyAdjustContentInsets false + :bounces false + :decelerationRate 0.9 + :horizontal true + :onLayout #(on-layout-change % component) + :onScrollBeginDrag #(reset! starting-position (get-current-position %)) + :onScrollEndDrag #(on-scroll-end % component @starting-position) + :showsHorizontalScrollIndicator false + :ref #(set! (.-scrollView component) %)} + (get-pages component state children)]])) + +(defn carousel [data children] + (let [component-data {:component-did-mount component-did-mount + :component-will-mount component-will-mount + :component-will-receive-props component-will-receive-props + :component-will-update component-will-update + :component-did-update component-did-update + :display-name "carousel" + :reagent-render reagent-render}] + (log/debug "Creating carousel component: " data) + (reagent.core/create-class component-data))) diff --git a/src/syng_im/components/carousel/styles.cljs b/src/syng_im/components/carousel/styles.cljs new file mode 100644 index 0000000000..def9de8c10 --- /dev/null +++ b/src/syng_im/components/carousel/styles.cljs @@ -0,0 +1,24 @@ +(ns syng-im.components.carousel.styles + (:require [syng-im.components.styles :refer [font + title-font + color-white + chat-background + online-color + selected-message-color + separator-color + text1-color + text2-color + toolbar-background1]])) + +(def scroll-view-container + {:flex 1}) + +(defn content-container [sneak gap] + {:paddingLeft (+ sneak (quot gap 2)) + :paddingRight (+ sneak (quot gap 2))}) + +(defn page [page-width margin] + {:width page-width + :justifyContent "center" + :marginLeft margin + :marginRight margin}) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery_popular.cljs b/src/syng_im/components/discovery/discovery_popular.cljs index 21b4fdab0a..df33467899 100644 --- a/src/syng_im/components/discovery/discovery_popular.cljs +++ b/src/syng_im/components/discovery/discovery_popular.cljs @@ -17,8 +17,7 @@ (log/debug "Got popular tags: " @popular-tags) (if (> (count @popular-tags) 0) [carousel {:pageStyle st/carousel-page-style - :pageWidth (- (page-width) 60) - :sneak 20} + :sneak 20} (for [tag @popular-tags] (discovery-popular-list (.-name tag) (.-count tag) navigator))] [text "None"]))) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery_popular_list.cljs b/src/syng_im/components/discovery/discovery_popular_list.cljs index afdb5fd77c..0291a1bb82 100644 --- a/src/syng_im/components/discovery/discovery_popular_list.cljs +++ b/src/syng_im/components/discovery/discovery_popular_list.cljs @@ -28,14 +28,12 @@ (defn discovery-popular-list [tag count navigator] (let [discoveries (subscribe [:get-discoveries-by-tag tag 3])] - (log/debug "Got discoveries for tag (" tag "): " @discoveries) [view {:style st/popular-list-container} - [view {:style st/row} - [view {:style st/column} + [view st/row + [view st/tag-name-container [touchable-highlight {:onPress #(dispatch [:show-discovery-tag tag navigator :push])} - [view {:style st/tag-name-container} - [text {:style st/tag-name} - (str " #" (name tag))]]]] + [text {:style st/tag-name} + (str " #" (name tag))]]] [view {:style st/tag-count-container} [text {:style st/tag-count} count]]] @@ -43,5 +41,4 @@ :enableEmptySections true :renderRow render-row :renderSeparator render-separator - :style st/popular-list}] - ])) + :style st/popular-list}]])) diff --git a/src/syng_im/components/discovery/discovery_popular_list_item.cljs b/src/syng_im/components/discovery/discovery_popular_list_item.cljs index 616fa9d7e2..49e08f2672 100644 --- a/src/syng_im/components/discovery/discovery_popular_list_item.cljs +++ b/src/syng_im/components/discovery/discovery_popular_list_item.cljs @@ -11,7 +11,6 @@ ) (defn discovery-popular-list-item [discovery] - (log/debug discovery) (r/as-element [view {:style st/popular-list-item} [view {:style st/popular-list-item-name-container} [text {:style st/popular-list-item-name} (aget discovery "name")] diff --git a/src/syng_im/components/discovery/styles.cljs b/src/syng_im/components/discovery/styles.cljs index da85fb9732..9c988558f9 100644 --- a/src/syng_im/components/discovery/styles.cljs +++ b/src/syng_im/components/discovery/styles.cljs @@ -75,7 +75,8 @@ :justifyContent "center"}) (def tag-name-container - {:backgroundColor "#eef2f5" + {:flexDirection "column" + :backgroundColor "#eef2f5" :borderRadius 5 :padding 4}) @@ -90,6 +91,7 @@ (def tag-count-container {:flex 0.2 + :flexDirection "column" :alignItems "flex-end" :paddingTop 10 :paddingRight 9})