showing sticky bar on scrolling discover screen (#14825)

This commit is contained in:
John Ngei 2023-02-06 15:41:34 +03:00 committed by GitHub
parent 89039cd79a
commit 91d0e106f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 325 additions and 127 deletions

View File

@ -210,8 +210,8 @@ PODS:
- React - React
- react-native-blob-util (0.13.18): - react-native-blob-util (0.13.18):
- React-Core - React-Core
- react-native-blur (3.6.1): - react-native-blur (4.3.0):
- React - React-Core
- react-native-camera-kit (8.0.4): - react-native-camera-kit (8.0.4):
- React - React
- react-native-cameraroll (4.0.4): - react-native-cameraroll (4.0.4):
@ -640,7 +640,7 @@ SPEC CHECKSUMS:
FBLazyVector: 352a8ca9bbc8e2f097d680747a8c97ecef12d469 FBLazyVector: 352a8ca9bbc8e2f097d680747a8c97ecef12d469
FBReactNativeSpec: 7dfb84f624136a45727c813ed21d130cd3e61beb FBReactNativeSpec: 7dfb84f624136a45727c813ed21d130cd3e61beb
Folly: b73c3869541e86821df3c387eb0af5f65addfab4 Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 6934faae5afbec23475648c8aeb6047ce973af65 glog: 997518ea2aa2d8cd5df9797b641b758d52ecf2bc
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352 HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8 Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
@ -658,7 +658,7 @@ SPEC CHECKSUMS:
React-jsinspector: fdbc08866b34ae8e1b788ea1cbd9f9d1ca2aa3d6 React-jsinspector: fdbc08866b34ae8e1b788ea1cbd9f9d1ca2aa3d6
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4 react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9 react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: 4568dd93d1d82748c180df8beb2d929c97b13b47 react-native-blur: 50c9feabacbc5f49b61337ebc32192c6be7ec3c3
react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f
react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2
react-native-config: c98128a72bc2c3a1ca72caec0b021f0fa944aa29 react-native-config: c98128a72bc2c3a1ca72caec0b021f0fa944aa29

View File

@ -255,7 +255,8 @@
{:background-color {:background-color
(if (= state :pressed) (if (= state :pressed)
(colors/theme-colors colors/neutral-100 colors/white) (colors/theme-colors colors/neutral-100 colors/white)
:transparent)} :transparent)
:width width}
style)} style)}
[rn/view [rn/view
{:style (merge {:style (merge

View File

@ -7,7 +7,7 @@
(defn community-card-view-item (defn community-card-view-item
[{:keys [name description locked images [{:keys [name description locked images
status tokens cover tags width]} on-press] status tokens cover tags width]} on-press]
[rn/touchable-opacity [rn/touchable-without-feedback
{:accessibility-label :community-card-item {:accessibility-label :community-card-item
:on-press on-press} :on-press on-press}
[rn/view {:style (style/community-card 20)} [rn/view {:style (style/community-card 20)}

View File

@ -12,23 +12,30 @@
:flex 1}) :flex 1})
(defn blur-slider (defn blur-slider
[animation] [animation height]
(reanimated/apply-animations-to-style (reanimated/apply-animations-to-style
{:transform [{:translateY animation}]} {:transform [{:translateY animation}]}
{:z-index 5 {:z-index 5
:top 0 :position :absolute
:position :absolute :top 0
:height (if platform/ios? 100 124) :height height
:width "100%" :right 0
:flex 1})) :left 0
:background-color (if platform/ios?
(colors/theme-colors
colors/white-opa-70
colors/neutral-95-opa-70)
:transparent)}))
(defn scroll-view-container (defn scroll-view-container
[border-radius] [border-radius]
{:position :absolute {:flex 1
:position :absolute
:top -48 :top -48
:left 0
:right 0
:overflow :scroll :overflow :scroll
:border-radius border-radius :border-radius border-radius})
:height "100%"})
(defn sticky-header-title (defn sticky-header-title
[animation] [animation]

View File

@ -27,9 +27,17 @@
(min maximum))) (min maximum)))
(defn scroll-page-header (defn scroll-page-header
[scroll-height name page-nav cover sticky-header] [scroll-height
height
name
page-nav
cover
sticky-header
top-nav
title-colum
navigate-back?]
(let [input-range (if platform/ios? [-47 10] [0 150]) (let [input-range (if platform/ios? [-47 10] [0 150])
output-range (if platform/ios? [-100 0] [-169 -45]) output-range (if platform/ios? [-208 0] [-208 -45])
y (reanimated/use-shared-value scroll-height) y (reanimated/use-shared-value scroll-height)
translate-animation (reanimated/interpolate y translate-animation (reanimated/interpolate y
input-range input-range
@ -47,35 +55,41 @@
[scroll-height]) [scroll-height])
[:<> [:<>
[reanimated/blur-view [reanimated/blur-view
{:blur-amount 32 {:blur-amount 20
:blur-type :xlight :blur-type :transparent
:overlay-color (if platform/ios? colors/white-opa-70 :transparent) :overlay-color :transparent
:style (style/blur-slider translate-animation)}] :style (style/blur-slider translate-animation height)}]
[rn/view [rn/view
{:style {:z-index 6 {:style {:z-index 6
:margin-top (if platform/ios? 44 0)}} :margin-top (if platform/ios? 44 0)}}
[reanimated/view (when cover
{:style (style/sticky-header-title opacity-animation)} [reanimated/view
[rn/image {:style (style/sticky-header-title opacity-animation)}
{:source cover [rn/image
:style style/sticky-header-image}] {:source cover
[quo/text :style style/sticky-header-image}]
{:size :paragraph-1 [quo/text
:weight :semi-bold {:size :paragraph-1
:style {:line-height 21}} :weight :semi-bold
name]] :style {:line-height 21}}
[quo/page-nav name]])
{:horizontal-description? true (if top-nav
:one-icon-align-left? true [top-nav]
:align-mid? false [quo/page-nav
:page-nav-color :transparent (merge {:horizontal-description? true
:mid-section {:type :text-with-description :one-icon-align-left? true
:main-text nil :align-mid? false
:description-img nil} :page-nav-color :transparent
:right-section-buttons page-nav :mid-section {:type :text-with-description
:left-section {:icon :i/close :main-text nil
:description-img nil}
:right-section-buttons page-nav}
(when navigate-back?
{:left-section {:icon :i/close
:icon-background-color (icon-color) :icon-background-color (icon-color)
:on-press #(rf/dispatch [:navigate-back])}}] :on-press #(rf/dispatch [:navigate-back])}}))])
(when title-colum
[title-colum])
sticky-header]])) sticky-header]]))
@ -101,14 +115,24 @@
(defn scroll-page (defn scroll-page
[_ _ _] [_ _ _]
(let [scroll-height (reagent/atom negative-scroll-position-0)] (let [scroll-height (reagent/atom negative-scroll-position-0)]
(fn [{:keys [cover-image page-nav-right-section-buttons name on-scroll]} (fn
sticky-header [{:keys [cover-image
children] page-nav-right-section-buttons
name
on-scroll
height
top-nav
title-colum
background-color
navigate-back?]}
sticky-header
children]
[:<> [:<>
[:f> scroll-page-header @scroll-height name page-nav-right-section-buttons cover-image [:f> scroll-page-header @scroll-height height name
sticky-header] page-nav-right-section-buttons cover-image sticky-header top-nav title-colum
navigate-back?]
[rn/scroll-view [rn/scroll-view
{:style (style/scroll-view-container {:content-container-style (style/scroll-view-container
(diff-with-max-min @scroll-height 16 0)) (diff-with-max-min @scroll-height 16 0))
:shows-vertical-scroll-indicator false :shows-vertical-scroll-indicator false
:scroll-event-throttle 16 :scroll-event-throttle 16
@ -119,17 +143,18 @@
"nativeEvent.contentOffset.y"))) "nativeEvent.contentOffset.y")))
(when on-scroll (when on-scroll
(on-scroll @scroll-height)))} (on-scroll @scroll-height)))}
[rn/view {:style {:height 151}} (when cover-image
[rn/image [rn/view {:style {:height 151}}
{:source cover-image [rn/image
:style {:overflow :visible {:source cover-image
:flex 1}}]] :style {:overflow :visible
:flex 1}}]])
(when children (when children
[rn/view [rn/view
{:flex 1 {:flex 1
:border-radius (diff-with-max-min @scroll-height 16 0) :border-radius (diff-with-max-min @scroll-height 16 0)
:background-color (colors/theme-colors :background-color background-color
colors/white :padding-top 48}
colors/neutral-90)} (when cover-image
[:f> display-picture @scroll-height cover-image] [:f> display-picture @scroll-height cover-image])
children])]]))) children])]])))

View File

@ -0,0 +1,55 @@
(ns status-im2.contexts.communities.discover.style
(:require [react-native.platform :as platform]))
(def screen-title-container
{:height 56
:padding-vertical 12
:justify-content :center})
(def featured-communities-header
{:flex-direction :row
:height 30
:padding-top 8
:margin-bottom 8
:padding-right 20
:justify-content :space-between})
(def featured-communities-title-container
{:flex-direction :row
:align-items :center})
(def featured-list-container
{:flex-direction :row
:overflow :hidden
:margin-bottom 24})
(defn discover-communities-segments
[fixed?]
(merge
{:padding-vertical 12
:height 56
:background-color :transparent}
(when-not fixed?
{:margin-top 12
:margin-bottom 4})))
(defn discover-screen-container
[background-color]
{:background-color background-color
:position :absolute
:top (if platform/ios? 0 44)
:bottom 0
:left 0
:right 0})
(defn blur-tabs-header
[]
{:padding-horizontal 20
:position :absolute
:top (if platform/ios? 56 60)
:height 56
:right 0
:left 0
:justify-content :center
:flex 1
:background-color :transparent})

View File

@ -4,10 +4,14 @@
[quo2.core :as quo] [quo2.core :as quo]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.react-native.resources :as resources] [status-im.react-native.resources :as resources]
[status-im2.contexts.communities.menus.community-options.view :as options] [status-im2.contexts.communities.menus.community-options.view :as options]
[status-im.ui.screens.communities.community :as community]
[status-im.ui.components.react :as react]
[react-native.platform :as platform]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.contexts.communities.discover.style :as style]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(def mock-community-item-data ;; TODO: remove once communities are loaded with this data. (def mock-community-item-data ;; TODO: remove once communities are loaded with this data.
@ -29,10 +33,9 @@
:resource (resources/get-image :podcasts)}]}}) :resource (resources/get-image :podcasts)}]}})
(defn render-fn (defn render-fn
[community-item _ _ {:keys [featured? width view-type]}] [community-item _ _ {:keys [width view-type]}]
(let [item (merge community-item (let [item (merge community-item
(get mock-community-item-data :data) (get mock-community-item-data :data))]
{:featured featured?})]
(if (= view-type :card-view) (if (= view-type :card-view)
[quo/community-card-view-item (assoc item :width width) [quo/community-card-view-item (assoc item :width width)
#(rf/dispatch [:navigate-to :community-overview (:id item)])] #(rf/dispatch [:navigate-to :community-overview (:id item)])]
@ -49,8 +52,7 @@
(defn screen-title (defn screen-title
[] []
[rn/view [rn/view
{:height 56 {:style style/screen-title-container}
:padding-vertical 12}
[quo/text [quo/text
{:accessibility-label :communities-screen-title {:accessibility-label :communities-screen-title
:weight :semi-bold :weight :semi-bold
@ -60,13 +62,9 @@
(defn featured-communities-header (defn featured-communities-header
[communities-count] [communities-count]
[rn/view [rn/view
{:flex-direction :row {:style style/featured-communities-header}
:height 30
:margin-bottom 8
:justify-content :space-between}
[rn/view [rn/view
{:flex-direction :row {:style style/featured-communities-title-container}
:align-items :center}
[quo/text [quo/text
{:accessibility-label :featured-communities-title {:accessibility-label :featured-communities-title
:weight :semi-bold :weight :semi-bold
@ -83,18 +81,34 @@
colors/neutral-50 colors/neutral-50
colors/neutral-40)}]]) colors/neutral-40)}]])
(defn discover-communities-segments
[selected-tab fixed]
[rn/view
{:style (style/discover-communities-segments fixed)}
[quo/tabs
{:size 32
:on-change #(reset! selected-tab %)
:default-active :all
:data [{:id :all
:label (i18n/label :t/all)
:accessibility-label :all-communities-tab}
{:id :open
:label (i18n/label :t/open)
:accessibility-label :open-communities-tab}
{:id :gated
:label (i18n/label :t/gated)
:accessibility-label :gated-communities-tab}]}]])
(defn featured-list (defn featured-list
[communities view-type] [communities view-type]
(let [view-size (reagent/atom 0)] (let [view-size (reagent/atom 0)]
(fn [] (fn []
[rn/view [rn/view
{:style {:flex-direction :row {:style style/featured-list-container
:overflow :hidden
:width "100%"
:margin-bottom 24}
:on-layout #(swap! view-size :on-layout #(swap! view-size
(fn [] (fn []
(oops/oget % "nativeEvent.layout.width")))} (- (oops/oget % "nativeEvent.layout.width") 20)))}
(when-not (= @view-size 0) (when-not (= @view-size 0)
[rn/flat-list [rn/flat-list
{:key-fn :id {:key-fn :id
@ -104,47 +118,134 @@
:separator [rn/view {:width 12}] :separator [rn/view {:width 12}]
:data communities :data communities
:render-fn render-fn :render-fn render-fn
:render-data {:featured? true :render-data {:width @view-size
:width @view-size
:view-type view-type}}])]))) :view-type view-type}}])])))
(defn discover-communities-header
[{:keys [featured-communities-count
featured-communities
view-type
selected-tab]}]
[react/animated-view
[screen-title]
[featured-communities-header featured-communities-count]
[featured-list featured-communities view-type]
[quo/separator]
[discover-communities-segments selected-tab false]])
(defn other-communities-list (defn other-communities-list
[communities view-type] [{:keys [communities communities-ids view-type]}]
[rn/flat-list [rn/view {:flex 1}
{:key-fn :id (map-indexed
:keyboard-should-persist-taps :always (fn [inner-index item]
:shows-horizontal-scroll-indicator false (let [community-id (when communities-ids item)
:separator [rn/view {:margin-bottom 16}] community (if communities
:data communities item
:render-fn render-fn [rf/sub [:communities/home-item community-id]])]
:render-data {:featured? false [rn/view
:width "100%" {:key (str inner-index (:id community))
:view-type view-type}}]) :margin-bottom 16}
(if (= view-type :card-view)
[quo/community-card-view-item
(merge community
(get mock-community-item-data :data))
#(rf/dispatch [:navigate-to :community-overview (:id community)])]
[quo/communities-list-view-item
{:on-press (fn []
(rf/dispatch [:communities/load-category-states (:id community)])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community (:id community)]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn []
;; TODO implement with quo2
[community/community-actions community])}])}
(merge community
(get mock-community-item-data :data))])]))
(if communities communities communities-ids))])
(defn communities-lists
[selected-tab view-type]
(let [ids-by-user-involvement (rf/sub [:communities/community-ids-by-user-involvement])
all-communities (rf/sub [:communities/sorted-communities])
tab @selected-tab]
[rn/view {:style {:flex 1}}
(case tab
:all
(other-communities-list {:communities all-communities
:view-type view-type})
:open
(other-communities-list {:communities-ids (:open ids-by-user-involvement)
:view-type view-type})
:gated
(other-communities-list {:communities-ids (:gated ids-by-user-involvement)
:view-type view-type})
[quo/information-box
{:type :error
:icon :i/info}
(i18n/label :t/error)])]))
(defn render-communities
[selected-tab
featured-communities-count
featured-communities
view-type]
(fn []
[rn/view {:padding-horizontal 20}
[discover-communities-header
{:selected-tab selected-tab
:view-type view-type
:featured-communities-count featured-communities-count
:featured-communities featured-communities}]
[communities-lists selected-tab view-type]]))
(defn render-sticky-header
[{:keys [selected-tab scroll-height]}]
(fn []
(when (> @scroll-height 360)
[rn/view
{:style (style/blur-tabs-header)}
[discover-communities-segments selected-tab true]])))
(defn discover-screen-content
[featured-communities]
(let [view-type (reagent/atom :card-view)
selected-tab (reagent/atom :all)
scroll-height (reagent/atom 0)
featured-communities-count (count featured-communities)]
(fn []
[scroll-page/scroll-page
{:name (i18n/label :t/discover-communities)
:on-scroll #(reset! scroll-height %)
:background-color (colors/theme-colors
colors/white
colors/neutral-95)
:navigate-back? :true
:height (if platform/ios?
(if (> @scroll-height 360)
156
100)
(if (> @scroll-height 360)
162
106))}
[render-sticky-header
{:selected-tab selected-tab
:scroll-height scroll-height}]
[render-communities
selected-tab
featured-communities-count
featured-communities
@view-type]])))
(defn discover (defn discover
[] []
(let [view-type (reagent/atom :card-view)] (let [featured-communities (rf/sub [:communities/featured-communities])]
(fn [] [rn/view
(let [communities (rf/sub [:communities/sorted-communities]) {:style (style/discover-screen-container (colors/theme-colors
featured-communities (rf/sub [:communities/featured-communities]) colors/white
featured-communities-count (count featured-communities)] colors/neutral-95))}
[safe-area/consumer [discover-screen-content featured-communities]]))
(fn []
[rn/view
{:style {:margin-left 20
:margin-right 20
:flex 1
:background-color (colors/theme-colors
colors/white
colors/neutral-90)}}
[quo/button
{:icon true
:type :grey
:size 32
:style {:margin-vertical 12}
:on-press #(rf/dispatch [:navigate-back])}
:i/close]
[screen-title]
[featured-communities-header featured-communities-count]
[featured-list featured-communities @view-type]
[other-communities-list communities @view-type]])]))))

View File

@ -56,7 +56,8 @@
(let [ids-by-user-involvement (rf/sub [:communities/community-ids-by-user-involvement]) (let [ids-by-user-involvement (rf/sub [:communities/community-ids-by-user-involvement])
tab @selected-tab] tab @selected-tab]
[rn/view [rn/view
{:style {:padding-horizontal 20 {:style {:flex 1
:padding-horizontal 20
:padding-vertical 12}} :padding-vertical 12}}
(case tab (case tab
:joined :joined

View File

@ -8,11 +8,13 @@
:margin-top 20}) :margin-top 20})
(def blur-channel-header (def blur-channel-header
{:position :absolute {:position :absolute
:top (if platform/ios? 56 60) :top (if platform/ios? 56 60)
:height 34 :height 34
:width "100%" :right 0
:flex 1}) :left 0
:flex 1
:background-color :transparent})
(def join-button (def join-button
{:width "100%" {:width "100%"

View File

@ -4,7 +4,6 @@
[quo2.core :as quo] [quo2.core :as quo]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.blur :as blur]
[react-native.platform :as platform] [react-native.platform :as platform]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.constants :as constants] [status-im2.constants :as constants]
@ -262,11 +261,8 @@
[_] [_]
(fn [{:keys [:enabled :label]}] (fn [{:keys [:enabled :label]}]
(when enabled (when enabled
[blur/view [rn/view
{:blur-amount 32 {:style style/blur-channel-header}
:blur-type :xlight
:overlay-color (if platform/ios? colors/white-opa-70 :transparent)
:style style/blur-channel-header}
[quo/divider-label [quo/divider-label
{:label (:label label) {:label (:label label)
:chevron-position :left}]]))) :chevron-position :left}]])))
@ -293,7 +289,18 @@
{:cover-image cover {:cover-image cover
:page-nav-right-section-buttons (page-nav-right-section-buttons id) :page-nav-right-section-buttons (page-nav-right-section-buttons id)
:name name :name name
:on-scroll #(reset! scroll-height %)} :on-scroll #(reset! scroll-height %)
:navigate-back? true
:background-color (colors/theme-colors
colors/white
colors/neutral-90)
:height (if platform/ios?
(if (> @scroll-height @first-channel-height)
134
100)
(if (> @scroll-height @first-channel-height)
140
106))}
[sticky-category-header [sticky-category-header
{:enabled (> @scroll-height @first-channel-height) {:enabled (> @scroll-height @first-channel-height)
@ -312,4 +319,3 @@
[rn/view [rn/view
{:style style/community-overview-container} {:style style/community-overview-container}
[community-card-page-view community]])) [community-card-page-view community]]))