diff --git a/src/js/worklets/header.js b/src/js/worklets/header.js new file mode 100644 index 000000000000..558952633f90 --- /dev/null +++ b/src/js/worklets/header.js @@ -0,0 +1,19 @@ +import {useDerivedValue, withTiming} from "react-native-reanimated"; + +export function headerContentOpacity(scrollY, threshold) { + return useDerivedValue(function () { + 'worklet'; + if (scrollY.value < threshold) { + return withTiming(0); + } else { + return withTiming(1); + } + }); +} + +export function headerContentPosition(scrollY, threshold, topBarHeight) { + return useDerivedValue(function () { + 'worklet'; + return scrollY.value < threshold ? withTiming(topBarHeight) : withTiming(0); + }); +} diff --git a/src/quo/components/navigation/page_nav/style.cljs b/src/quo/components/navigation/page_nav/style.cljs index 9be23ab02886..f2966c04ca0e 100644 --- a/src/quo/components/navigation/page_nav/style.cljs +++ b/src/quo/components/navigation/page_nav/style.cljs @@ -1,6 +1,7 @@ (ns quo.components.navigation.page-nav.style (:require - [quo.foundations.colors :as colors])) + [quo.foundations.colors :as colors] + [react-native.reanimated :as reanimated])) (defn container [margin-top] @@ -21,6 +22,16 @@ :justify-content (if centered? :center :flex-start) :opacity center-opacity}) +(defn center-content-container-animation + [{:keys [centered? center-opacity has-animations? translate-animation opacity-animation]}] + (if has-animations? + (reanimated/apply-animations-to-style + {:transform [{:translate-y translate-animation}] + :opacity opacity-animation} + (center-content-container centered? center-opacity)) + (center-content-container centered? center-opacity))) + + (def right-actions-container {:flex-direction :row}) diff --git a/src/quo/components/navigation/page_nav/view.cljs b/src/quo/components/navigation/page_nav/view.cljs index 00802d221d4f..6760189fbe53 100644 --- a/src/quo/components/navigation/page_nav/view.cljs +++ b/src/quo/components/navigation/page_nav/view.cljs @@ -11,7 +11,9 @@ [quo.components.markdown.text :as text] [quo.components.navigation.page-nav.style :as style] [quo.theme :as theme] - [react-native.core :as rn])) + [react-native.core :as rn] + [react-native.reanimated :as reanimated] + [utils.worklets.header :as header-worklet])) (def ^:private button-type {:white :grey @@ -85,14 +87,29 @@ :else nil)]) +(def header-height 155) +(def page-nav-height 25) +(def threshold (- header-height page-nav-height)) + (defn- title-center - [{:keys [centered? title center-opacity]}] - [rn/view {:style (style/center-content-container centered? center-opacity)} - [text/text - {:weight :medium - :size :paragraph-1 - :number-of-lines 1} - title]]) + [{:keys [centered? title center-opacity scroll-y]}] + (let [translate-animation (when scroll-y + (header-worklet/header-content-position scroll-y + threshold + page-nav-height)) + opacity-animation (when scroll-y + (header-worklet/header-content-opacity scroll-y threshold))] + [reanimated/view + {:style (style/center-content-container-animation {:has-animations? (not (nil? scroll-y)) + :centered? centered? + :center-opacity center-opacity + :translate-animation translate-animation + :opacity-animation opacity-animation})} + [text/text + {:weight :medium + :size :paragraph-1 + :number-of-lines 1} + title]])) (defn- dropdown-center [{:keys [theme background dropdown-on-press dropdown-selected? dropdown-text center-opacity]}] @@ -295,6 +312,7 @@ `:title` - title - text-align: `:center` or `:left` + - scroll-y: a shared value (optional) `:dropdown` - dropdown-on-press: a callback - dropdown-selected?: a boolean diff --git a/src/status_im/contexts/profile/settings/view.cljs b/src/status_im/contexts/profile/settings/view.cljs index 0093fd3bb885..3bd0406ab313 100644 --- a/src/status_im/contexts/profile/settings/view.cljs +++ b/src/status_im/contexts/profile/settings/view.cljs @@ -9,6 +9,7 @@ [status-im.contexts.profile.settings.header.view :as settings.header] [status-im.contexts.profile.settings.list-items :as settings.items] [status-im.contexts.profile.settings.style :as style] + [status-im.contexts.profile.utils :as profile.utils] [utils.debounce :as debounce] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -42,7 +43,9 @@ (let [insets (safe-area/get-insets) customization-color (rf/sub [:profile/customization-color]) scroll-y (reanimated/use-shared-value 0) - logout-press #(rf/dispatch [:multiaccounts.logout.ui/logout-pressed])] + logout-press #(rf/dispatch [:multiaccounts.logout.ui/logout-pressed]) + profile (rf/sub [:profile/profile]) + full-name (profile.utils/displayed-name profile)] [quo/overlay {:type :shell} [rn/view {:key :header @@ -50,7 +53,11 @@ :inset (:top insets) :theme theme})} [quo/page-nav - {:background :blur + {:title full-name + :background :blur + :type :title + :text-align :left + :scroll-y scroll-y :icon-name :i/close :on-press #(rf/dispatch [:navigate-back]) :right-side [{:icon-name :i/multi-profile :on-press #(rf/dispatch [:open-modal :sign-in])} diff --git a/src/utils/worklets/header.cljs b/src/utils/worklets/header.cljs new file mode 100644 index 000000000000..7ae5d64a1b92 --- /dev/null +++ b/src/utils/worklets/header.cljs @@ -0,0 +1,16 @@ +(ns utils.worklets.header) + +(def ^:private worklets (js/require "../src/js/worklets/header.js")) + +(defn header-content-opacity + [scroll-y threshold] + (.headerContentOpacity ^js worklets + scroll-y + threshold)) + +(defn header-content-position + [scroll-y threshold top-bar-height] + (.headerContentPosition ^js worklets + scroll-y + threshold + top-bar-height))