[#7589] Stickers packs horizontal scrolling

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2019-02-26 18:11:36 +03:00
parent 82493e2742
commit 4c2054afd4
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
3 changed files with 81 additions and 33 deletions

View File

@ -3,10 +3,10 @@
(def stickers-panel {:flex 1 :margin 5 :flex-direction :row :justify-content :flex-start :flex-wrap :wrap})
(defn pack-icon [background-color icon-size]
(defn pack-icon [background-color icon-size icon-horizontal-margin]
{:background-color background-color
:margin-vertical 5
:margin-horizontal 8
:margin-horizontal icon-horizontal-margin
:height icon-size
:width icon-size
:border-radius (/ icon-size 2)

View File

@ -6,7 +6,15 @@
[status-im.ui.components.colors :as colors]
[status-im.i18n :as i18n]
[status-im.ui.screens.chat.stickers.styles :as styles]
[status-im.ui.components.animation :as anim]))
[status-im.ui.components.animation :as anim]
[reagent.core :as reagent]))
(def icon-size 28)
(def icon-horizontal-margin 8)
(def indicator-width 16)
(def dx (- (+ icon-horizontal-margin (/ icon-size 2)) (/ indicator-width 2)))
(def icon-container (+ (* icon-horizontal-margin 2) icon-size))
(def scroll-x (reagent/atom 0))
(defn button [show-stickers?]
[react/touchable-highlight
@ -27,33 +35,65 @@
[react/text {:style {:font-size 15 :color colors/blue}}
(i18n/label :t/get-stickers)]]]])
(defn- stickers-panel [stickers]
[react/scroll-view {:style {:flex 1} :condtent-container-style {:flex 1}}
[react/view {:style styles/stickers-panel}
(for [{:keys [uri] :as sticker} stickers]
^{:key uri}
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
:on-press #(re-frame/dispatch [:chat/send-sticker sticker])}
[react/image {:style {:resize-mode :cover :width "100%" :height "100%"} :source {:uri uri}}]])]])
(defn- stickers-panel [stickers window-width]
[react/view {:width window-width :flex 1}
[react/scroll-view
[react/view {:style styles/stickers-panel}
(for [{:keys [uri] :as sticker} stickers]
^{:key uri}
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
:on-press #(re-frame/dispatch [:chat/send-sticker sticker])}
[react/image {:style {:resize-mode :cover :width "100%" :height "100%"} :source {:uri uri}}]])]]])
(defview recent-stickers-panel []
(defview recent-stickers-panel [window-width]
(letsubs [stickers [:stickers/recent]]
(if (seq stickers)
[stickers-panel stickers]
[react/view {:style {:flex 1 :align-items :center :justify-content :center}}
[stickers-panel stickers window-width]
[react/view {:style {:flex 1 :align-items :center :justify-content :center :width window-width}}
[vector-icons/icon :stickers-icons/stickers-big {:color colors/gray}]
[react/text {:style {:margin-top 8 :font-size 17}} (i18n/label :t/recently-used-stickers)]])))
(def icon-size 28)
(defn update-scroll-position [ref installed-packs selected-pack window-width]
(when ref
(let [x (if (= selected-pack :recent)
0
(* (inc (some #(when (= selected-pack (:id (second %))) (first %))
(map-indexed vector installed-packs)))
window-width))]
(.scrollTo ref (clj->js {:x x :animated true})))))
(defn pack-icon [{:keys [id on-press selected? background-color]
(defn on-scroll [e installed-packs window-width]
(let [num (/ (.-nativeEvent.contentOffset.x e) window-width)
pack-id (if (zero? num)
:recent
(get-in (vec installed-packs) [(dec num) :id]))]
(when pack-id
(re-frame/dispatch [:stickers/select-pack pack-id]))))
(defview stickers-paging-panel [installed-packs selected-pack]
(letsubs [ref (atom nil)
window-width [:dimensions/window-width]]
{:component-will-update (fn [_ [_ installed-packs selected-pack]]
(update-scroll-position @ref installed-packs selected-pack window-width))
:component-did-mount #(update-scroll-position @ref installed-packs selected-pack window-width)}
[react/scroll-view {:style {:flex 1} :horizontal true :paging-enabled true
:ref #(reset! ref %)
:shows-horizontal-scroll-indicator false
:on-momentum-scroll-end #(on-scroll % installed-packs window-width)
:scrollEventThrottle 8
:on-scroll #(reset! scroll-x (.-nativeEvent.contentOffset.x %))}
^{:key "recent"}
[recent-stickers-panel window-width]
(for [{:keys [stickers id]} installed-packs]
^{:key (str "sticker" id)}
[stickers-panel (map #(assoc % :pack id) stickers) window-width])]))
(defn pack-icon [{:keys [id on-press background-color]
:or {on-press #(re-frame/dispatch [:stickers/select-pack id])}} icon]
[react/touchable-highlight {:on-press on-press}
[react/view {:style {:align-items :center}}
[react/view {:style (styles/pack-icon background-color icon-size)}
icon]
[react/view {:style {:margin-bottom 5 :height 2 :width 16 :border-radius 1
:background-color (if selected? colors/blue colors/white)}}]]])
[react/view {:style (styles/pack-icon background-color icon-size icon-horizontal-margin)}
icon]]])
(defn pack-stickers [packs pack-id]
(let [{:keys [stickers id]} (some #(when (= pack-id (:id %)) %) packs)]
@ -67,6 +107,12 @@
(anim/timing alpha-value {:toValue 1
:duration 500})])))
(defview scroll-indicator []
(letsubs [window-width [:dimensions/window-width]]
[react/view {:style {:margin-bottom 5 :height 2 :width indicator-width :border-radius 1
:margin-left (+ dx (* icon-container (/ @scroll-x window-width)))
:background-color colors/blue}}]))
(defview stickers-view []
(letsubs [selected-pack [:stickers/selected-pack]
installed-packs [:stickers/installed-packs-vals]
@ -81,10 +127,9 @@
[react/animated-view {:style {:background-color :white :height (if input-focused? 0 bottom-anim-value)
:opacity alpha-value}}
(cond
(= selected-pack :recent) [recent-stickers-panel]
(= selected-pack :recent) [stickers-paging-panel installed-packs selected-pack]
(not (seq installed-packs)) [no-stickers-yet-panel]
(nil? selected-pack) [recent-stickers-panel]
:else [stickers-panel (pack-stickers installed-packs selected-pack)])
:else [stickers-paging-panel installed-packs selected-pack])
[react/view {:style {:flex-direction :row :padding-horizontal 4}}
[pack-icon {:on-press #(do
(re-frame/dispatch [:stickers/load-packs])
@ -93,11 +138,13 @@
[vector-icons/icon :main-icons/add {:width 20 :height 20 :color colors/white}]]
[react/view {:width 2}]
[react/scroll-view {:horizontal true :style {:padding-left 2}}
[pack-icon {:id :recent :selected? (or (= :recent selected-pack) (and (nil? selected-pack) (seq installed-packs)))
:background-color colors/white}
[vector-icons/icon :stickers-icons/recent {:color colors/gray}]]
(for [{:keys [id thumbnail]} installed-packs]
^{:key id}
[pack-icon {:id id :selected? (= id selected-pack)}
[react/image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
:source {:uri thumbnail}}]])]]]))
[react/view
[react/view {:style {:flex-direction :row}}
[pack-icon {:id :recent :background-color colors/white}
[vector-icons/icon :stickers-icons/recent {:color colors/gray}]]
(for [{:keys [id thumbnail]} installed-packs]
^{:key id}
[pack-icon {:id id}
[react/image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
:source {:uri thumbnail}}]])]
[scroll-indicator]]]]]))

View File

@ -388,5 +388,6 @@
(hex-to-value val type)))))
(defn decode [bytes types]
(let [offsets (get-offsets types)]
(map (dec-type bytes) offsets types)))
(when-not (empty? bytes)
(let [offsets (get-offsets types)]
(map (dec-type bytes) offsets types))))