Skip to content

Commit

Permalink
[#17986] refactor: apply header animation on scroll list
Browse files Browse the repository at this point in the history
  • Loading branch information
mohsen-ghafouri committed Nov 27, 2023
1 parent 34e472f commit 13b8e73
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/quo/foundations/colors.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
(def black-opa-30 (alpha black 0.3))
(def black-opa-60 (alpha black 0.6))
(def onboarding-header-black "#000716")

(def border-avatar-light "#475060") ;; Simulate blur transparent avatar's border in light mode
;;;;Primary

;;Solid
Expand Down
44 changes: 44 additions & 0 deletions src/status_im2/contexts/profile/settings/header/avatar.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
(ns status-im2.contexts.profile.settings.header.avatar
(:require [quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.reanimated :as reanimated]
[status-im2.contexts.profile.settings.header.style :as style]))

(defonce ^:const scroll-animation-input-range [0 50])

(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})

(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.5]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)
theme (quo.theme/get-theme)]
[reanimated/view
{:style (style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]))

(defn view
[props]
[:f> f-avatar props])
37 changes: 24 additions & 13 deletions src/status_im2/contexts/profile/settings/header/header_shape.cljs
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
(ns status-im2.contexts.profile.settings.header.header-shape
(:require [quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.svg :as svg]
[status-im2.contexts.profile.settings.header.style :as style]))

(defn left-shape
(defonce ^:const scroll-animation-input-range [0 45 50])

(defn left-radius
[background-color]
[svg/svg {:width "109" :height "68" :viewBox "0 0 109 68" :fill "none"}
[svg/svg {:width "20" :height "20" :viewBox "0 0 20 20" :fill "none"}
[svg/path
{:d
"M0 0H109V48H103.821C101.8 25.574 82.9522 8 60 8C36.9215 8 17.993 25.768 16.1475 48.3707C6.94517 50.1664 0 58.2721 0 68V0Z"
{:d "M20 0C7 2 0 10 0 20V0H15Z"
:fill background-color}]])

(defn right-shape
(defn right-radius
[background-color]
[svg/svg {:width "25" :height "68" :viewBox "0 0 25 68" :fill "none"}
[svg/svg {:width "20" :height "21" :viewBox "0 0 20 21" :fill "none"}
[svg/path
{:d "M0.000610352 0H24.5005V68L24.5003 68C24.5003 56.9543 15.546 48 4.50031 48H0.000610352V0Z"
{:d "M20 20V0H0C11 0 20 9 20 20Z"
:fill background-color}]])

(defn view
[customization-color theme]
(let [background-color (colors/resolve-color customization-color theme 40)]
[rn/view {:style style/header-shape-container}
[left-shape background-color]

(defn f-view
[{:keys [scroll-y customization-color theme]}]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 1 0])]
[rn/view
[rn/view {:style (style/header-middle-shape background-color)}]
[right-shape background-color]]))
[reanimated/view {:style (style/radius-container opacity-animation)}
[left-radius background-color]
[right-radius background-color]]]))

(defn view
[props]
[:f> f-view props])
34 changes: 25 additions & 9 deletions src/status_im2/contexts/profile/settings/header/style.cljs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
(ns status-im2.contexts.profile.settings.header.style
(:require [quo.foundations.colors :as colors]))
(defonce ^:const navigation-bar-height 100)
(defonce ^:const header-offset 56)
(:require [quo.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))

(defn header-view
[customization-color theme]
{:background-color (colors/resolve-color customization-color theme 40)
:min-height 100
:flex 1})

(def avatar-container
(def avatar-row-wrapper
{:display :flex
:padding-left 20
:padding-left 16
:padding-right 12
:margin-top -56
:margin-top -60
:margin-bottom -4
:align-items :flex-end
:justify-content :space-between
:flex-direction :row})
Expand All @@ -22,11 +22,27 @@
{:padding-horizontal 20
:padding-vertical 12})

(def header-shape-container
{:flex-direction :row})

(defn header-middle-shape
[background-color]
{:background-color background-color
:height 48
:flex-grow 1})

(defn radius-container
[opacity-animation]
(reanimated/apply-animations-to-style
{:opacity opacity-animation}
{:flex-direction :row
:justify-content :space-between}))

(defn avatar-container
[theme scale-animation top-margin-animation side-margin-animation]
(reanimated/apply-animations-to-style
{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 100}))
41 changes: 22 additions & 19 deletions src/status_im2/contexts/profile/settings/header/view.cljs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
(ns status-im2.contexts.profile.settings.header.view
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.header.avatar :as header.avatar]
[status-im2.contexts.profile.settings.header.header-shape :as header.shape]
[status-im2.contexts.profile.settings.header.style :as style]
[status-im2.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

(defn- f-view
[theme]
[{:keys [theme scroll-y]}]
(let [{:keys [public-key emoji-hash] :as profile} (rf/sub [:profile/profile-with-image])
online? (rf/sub [:visibility-status-updates/online?
public-key])
Expand All @@ -19,29 +20,31 @@
profile-picture (profile.utils/photo profile)
emoji-string (string/join emoji-hash)]
[rn/view
[header.shape/view customization-color theme]
[rn/view {:style style/avatar-container}
[quo/user-avatar
{:full-name full-name
[header.shape/view
{:scroll-y scroll-y
:customization-color customization-color
:theme theme}]
[rn/view {:style style/avatar-row-wrapper}
[header.avatar/view
{:scroll-y scroll-y
:display-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]
[quo/dropdown
{:background :blur
:size :size-32
:type :outline
:icon? true
:icon-name :i/online}
(i18n/label :t/status-always-online)]]
:profile-picture profile-picture}]
[rn/view {:style {:margin-bottom 4}}
[quo/dropdown
{:background :blur
:size :size-32
:type :outline
:icon? true
:icon-name :i/online
:on-press not-implemented/alert}
(i18n/label :t/online)]]]
[quo/text-combinations
{:container-style style/title-container
:emoji-hash emoji-string
:title full-name}]]))

(defn- internal-header-view
(defn view
[params]
[:f> f-view params])
(def view (quo.theme/with-theme internal-header-view))
32 changes: 24 additions & 8 deletions src/status_im2/contexts/profile/settings/view.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
(ns status-im2.contexts.profile.settings.view
(:require [quo.core :as quo]
(:require [oops.core :as oops]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.constants :as settings.constants]
Expand All @@ -13,16 +15,26 @@

(defn- f-settings-item-view
[data]
(println data)
[quo/category
{:list-type :settings
:blur? true
:data data}])

(defn scroll-handler
[event scroll-y]
(let [current-y (oops/oget event "nativeEvent.contentOffset.y")]
(reanimated/set-shared-value scroll-y current-y)))

(def footer
[rn/view {:style style/footer-container}
[quo/button {:type :danger :icon-left :i/log-out}
(i18n/label :t/logout)]])

(defn- settings-view
[theme]
(let [insets (safe-area/get-insets)
customization-color (rf/sub [:profile/customization-color])]
customization-color (rf/sub [:profile/customization-color])
scroll-y (reanimated/use-shared-value 0)]
[quo/overlay {:type :shell}
[rn/view {:style {:flex 1}}
[rn/view
Expand All @@ -38,14 +50,18 @@
{:icon-name :i/share
:on-press #(debounce/dispatch-and-chill [:open-modal :share-shell] 1000)}]}]]
[rn/flat-list
{:header [settings.header/view]
{:header [settings.header/view {:scroll-y scroll-y}]
:data settings.constants/settings-items
:key-fn str
:shows-vertical-scroll-indicator false
:render-fn f-settings-item-view
:footer [rn/view {:style style/footer-container}
[quo/button {:type :danger :icon-left :i/log-out}
(i18n/label :t/logout)]]
:footer footer
:scroll-event-throttle 16
:on-scroll #(scroll-handler % scroll-y)
:bounces false}]]]))

(def view (quo.theme/with-theme settings-view))
(defn- internal-view
[props]
[:f> settings-view props])

(def view (quo.theme/with-theme internal-view))

0 comments on commit 13b8e73

Please sign in to comment.