From 308c0771e8f163b2638df805b25ee6183375db3a Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 13 Mar 2025 13:58:45 -0600 Subject: [PATCH 01/16] Fix page-nav community variant not aligned --- .../components/navigation/page_nav/style.cljs | 10 ++++----- .../components/navigation/page_nav/view.cljs | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/quo/components/navigation/page_nav/style.cljs b/src/quo/components/navigation/page_nav/style.cljs index 4e1f6763d4b..9475a81926d 100644 --- a/src/quo/components/navigation/page_nav/style.cljs +++ b/src/quo/components/navigation/page_nav/style.cljs @@ -32,12 +32,10 @@ {:width 12}) (defn right-content - [min-size?] - (merge - {:flex-grow 1 - :flex-basis 1} - (when min-size? - {:min-height 32}))) + [min-size? centered-content?] + (cond-> {} + centered-content? (assoc :flex-grow 1 :flex-basis 1) + min-size? (assoc :min-height 32))) (def token-logo {:width 16 :height 16}) diff --git a/src/quo/components/navigation/page_nav/view.cljs b/src/quo/components/navigation/page_nav/view.cljs index 8c9d56f8338..d05c7879704 100644 --- a/src/quo/components/navigation/page_nav/view.cljs +++ b/src/quo/components/navigation/page_nav/view.cljs @@ -87,9 +87,10 @@ (defn- right-content [{:keys [background content max-actions min-size? support-account-switcher? - behind-overlay?] - :or {support-account-switcher? true}}] - [rn/view (style/right-content min-size?) + behind-overlay? centered-content?] + :or {support-account-switcher? true + centered-content? true}}] + [rn/view (style/right-content min-size? centered-content?) (when (coll? content) (into [rn/view {:style style/right-actions-container}] (add-right-buttons-xf max-actions background behind-overlay? support-account-switcher?) @@ -260,15 +261,15 @@ right-side :none background :white} :as props}] - (let [center-content-container-style (reanimated/apply-animations-to-style + (let [centered-content? (case type + :title (= text-align :center) + (:dropdown :wallet-networks) true + false) + center-content-container-style (reanimated/apply-animations-to-style (if center-opacity {:opacity center-opacity} nil) - (style/center-content-container - (case type - :title (= text-align :center) - (:dropdown :wallet-networks) true - false))) + (style/center-content-container centered-content?)) props-with-style (assoc props :center-content-container-style center-content-container-style)] @@ -342,6 +343,7 @@ {:background background :content right-side :max-actions 3 - :support-account-switcher? false}]] + :support-account-switcher? false + :centered-content? centered-content?}]] nil))) From b2585d53c9e173d9943d56975b45195da514edf8 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 13 Mar 2025 13:59:40 -0600 Subject: [PATCH 02/16] fix(communities): reimplement community overview --- src/js/worklets/communities.js | 286 +++++++ src/react_native/gesture.cljs | 7 + src/react_native/reanimated.cljs | 7 +- .../contexts/communities/overview/style.cljs | 166 +++- .../contexts/communities/overview/view.cljs | 706 ++++++++++-------- src/status_im/subs/communities.cljs | 39 + src/utils/worklets/communities.cljs | 17 + 7 files changed, 901 insertions(+), 327 deletions(-) create mode 100644 src/js/worklets/communities.js create mode 100644 src/utils/worklets/communities.cljs diff --git a/src/js/worklets/communities.js b/src/js/worklets/communities.js new file mode 100644 index 00000000000..0470cb640d5 --- /dev/null +++ b/src/js/worklets/communities.js @@ -0,0 +1,286 @@ +import { + useDerivedValue, + useAnimatedStyle, + interpolate, + scrollTo, + withTiming, + cancelAnimation, + withDecay, +} from 'react-native-reanimated'; + +import { Platform } from 'react-native'; + +export function useLogoStyles({ + scrollAmount, + expandHeaderThreshold, + sheetDisplacementThreshold, + textMovementThreshold, +}) { + return useAnimatedStyle(() => { + const firstDisplacement = scrollAmount.value < expandHeaderThreshold; + if (firstDisplacement) { + return { + transform: [ + { translateX: 20 }, + { translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [0, -42.5], 'clamp') }, + { scale: interpolate(scrollAmount.value, [0, textMovementThreshold], [1, 0.4], 'clamp') }, + ], + }; + } else { + return { + transform: [ + { translateX: 20 }, + { + translateY: interpolate( + scrollAmount.value, + [expandHeaderThreshold, sheetDisplacementThreshold], + [-42.5, -50.5], + 'clamp', + ), + }, + { scale: 0.4 }, + ], + }; + } + }); +} + +export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDisplacementThreshold }) { + return useAnimatedStyle(() => { + const firstDisplacement = scrollAmount.value < expandHeaderThreshold; + if (firstDisplacement) { + return { + transform: [{ translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [40, 0], 'clamp') }], + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + }; + } else { + const radius = interpolate( + scrollAmount.value, + [expandHeaderThreshold, sheetDisplacementThreshold], + [20, 0], + 'clamp', + ); + return { + transform: [ + { + translateY: interpolate( + scrollAmount.value, + [expandHeaderThreshold, sheetDisplacementThreshold], + [0, -8], + 'clamp', + ), + }, + ], + borderTopLeftRadius: radius, + borderTopRightRadius: radius, + }; + } + }); +} + +export function useNameStyles({ scrollAmount, expandHeaderThreshold, textMovementThreshold }) { + return useAnimatedStyle(() => { + return { + transform: [ + { + translateX: interpolate(scrollAmount.value, [textMovementThreshold, expandHeaderThreshold], [0, 40], 'clamp'), + }, + { + translateY: interpolate( + scrollAmount.value, + [textMovementThreshold, expandHeaderThreshold], + [0, -44.5], + 'clamp', + ), + }, + ], + }; + }); +} + +export function useInfoStyles({ scrollAmount, infoOpacityThreshold }) { + return useAnimatedStyle(() => { + return { + opacity: interpolate(scrollAmount.value, [0, infoOpacityThreshold], [1, 0.2], 'extend'), + }; + }); +} + +export function useChannelsStyles({ + scrollAmount, + headerHeight, + expandHeaderThreshold, + sheetDisplacementThreshold, + expandHeaderLimit, +}) { + return useAnimatedStyle(() => { + const headerDisplacement = (headerHeight.value - 55.5) * -1; + const firstDisplacement = scrollAmount.value < expandHeaderThreshold; + const secondDisplacement = scrollAmount.value > sheetDisplacementThreshold; + if (firstDisplacement) { + return { + transform: [ + { + translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [39, headerDisplacement], 'clamp'), + }, + ], + }; + } else if (secondDisplacement) { + return { + transform: [ + { + translateY: interpolate( + scrollAmount.value, + [sheetDisplacementThreshold, expandHeaderLimit], + [headerDisplacement - 8, headerDisplacement - 64], + 'clamp', + ), + }, + ], + }; + } else { + return { + transform: [ + { + translateY: interpolate( + scrollAmount.value, + [expandHeaderThreshold, sheetDisplacementThreshold], + [headerDisplacement, headerDisplacement - 8], + 'clamp', + ), + }, + ], + }; + } + }, [headerHeight.value]); +} + +export function useScrollTo({ animatedRef, scrollAmount, expandHeaderLimit }) { + const isAndroid = Platform.OS === 'android'; + return useDerivedValue(() => { + scrollTo(animatedRef, 0, scrollAmount.value - expandHeaderLimit, isAndroid); + }); +} + +export function useHeaderOpacity({ scrollAmount, expandHeaderThreshold, sheetDisplacementThreshold }) { + return useDerivedValue(() => { + return interpolate(scrollAmount.value, [expandHeaderThreshold, sheetDisplacementThreshold], [0, 1], 'clamp'); + }); +} + +export function useOppositeHeaderOpacity(headerOpacity) { + return useDerivedValue(() => { + return 1 - headerOpacity.value; + }); +} + +export function useNavContentOpacity({ scrollAmount, sheetDisplacementThreshold, expandHeaderLimit }) { + return useDerivedValue(() => { + return interpolate(scrollAmount.value, [sheetDisplacementThreshold, expandHeaderLimit], [0, 1], 'clamp'); + }); +} + +export function onScrollAnimationEnd( + scrollAmount, + scrollStart, + expandHeaderThreshold, + snapHeaderThreshold, + expandHeaderLimit, +) { + 'worklet'; + return function () { + 'worklet'; + if (scrollAmount.value > snapHeaderThreshold && scrollAmount.value <= expandHeaderThreshold) { + scrollStart.value = withTiming(-expandHeaderThreshold, { duration: 300 }); + scrollAmount.value = withTiming(expandHeaderThreshold, { duration: 300 }); + } + + if (scrollAmount.value > expandHeaderThreshold) { + scrollStart.value = -scrollAmount.value; + } + + if (scrollAmount.value <= snapHeaderThreshold) { + scrollStart.value = withTiming(0, { duration: 300 }); + scrollAmount.value = withTiming(0, { duration: 300 }); + } + + if (scrollAmount.value > expandHeaderThreshold && scrollAmount.value < expandHeaderLimit) { + if (scrollAmount.value >= (expandHeaderLimit - expandHeaderThreshold) * 0.65 + expandHeaderThreshold) { + scrollAmount.value = withTiming(expandHeaderLimit, { duration: 300 }); + scrollStart.value = withTiming(-expandHeaderLimit, { duration: 300 }); + } else { + scrollAmount.value = withTiming(expandHeaderThreshold, { duration: 300 }); + scrollStart.value = withTiming(-expandHeaderThreshold, { duration: 300 }); + } + } + }; +} + +export function onPanStart(scrollStart, scrollAmount) { + return function () { + 'worklet'; + cancelAnimation(scrollStart); + cancelAnimation(scrollAmount); + scrollStart.value = -1 * scrollAmount.value; + }; +} + +export function onPanUpdate({ scrollStart, scrollAmount, maxScroll, expandHeaderLimit }) { + return function (event) { + 'worklet'; + const newScrollAmount = -1 * (event.translationY + scrollStart.value); + if (newScrollAmount <= 0) { + scrollAmount.value = 0; + } else { + const limit = expandHeaderLimit + maxScroll.value; + scrollAmount.value = newScrollAmount <= limit ? newScrollAmount : limit; + } + }; +} + +export function onPanEnd({ + scrollStart, + scrollAmount, + maxScroll, + expandHeaderLimit, + expandHeaderThreshold, + snapHeaderThreshold, +}) { + const isIOS = Platform.OS === 'ios'; + return function (event) { + 'worklet'; + scrollStart.value = -scrollAmount.value; + const endAnimation = onScrollAnimationEnd( + scrollAmount, + scrollStart, + expandHeaderThreshold, + snapHeaderThreshold, + expandHeaderLimit, + ); + if (scrollAmount.value < expandHeaderLimit) { + endAnimation(); + } else { + const maxValue = maxScroll.value + expandHeaderLimit; + const decelerationRate = isIOS ? { deceleration: 0.9997 } : { deceleration: 0.999 }; + + scrollStart.value = withDecay({ + ...{ + velocity: event.velocityY, + clamp: [-1 * maxValue, 0], + }, + ...decelerationRate, + }); + scrollAmount.value = withDecay( + { + ...{ + velocity: -1 * event.velocityY, + clamp: [0, maxValue], + }, + ...decelerationRate, + }, + endAnimation, + ); + } + }; +} diff --git a/src/react_native/gesture.cljs b/src/react_native/gesture.cljs index b7e0a4da8fb..69f660080c4 100644 --- a/src/react_native/gesture.cljs +++ b/src/react_native/gesture.cljs @@ -3,6 +3,7 @@ ["react-native-gesture-handler" :refer (Gesture GestureDetector + Directions RectButton Swipeable TouchableWithoutFeedback @@ -13,6 +14,8 @@ [react-native.flat-list :as rn-flat-list] [reagent.core :as reagent])) +(def directions (js->clj Directions :keywordize-keys true)) + (def gesture-detector (reagent/adapt-react-class GestureDetector)) (def gesture-handler-root-hoc gestureHandlerRootHOC) @@ -21,10 +24,14 @@ (defn gesture-pan [] (.Pan ^js Gesture)) +(defn gesture-native [] (.Native ^js Gesture)) + (defn gesture-long-press [] (.LongPress ^js Gesture)) (defn gesture-pinch [] (.Pinch ^js Gesture)) +(defn gesture-fling [] (.Fling ^js Gesture)) + (defn on-begin [gesture handler] (.onBegin ^js gesture handler)) (defn on-start [gesture handler] (.onStart ^js gesture handler)) diff --git a/src/react_native/reanimated.cljs b/src/react_native/reanimated.cljs index 63b0717343a..c570ace9fb2 100644 --- a/src/react_native/reanimated.cljs +++ b/src/react_native/reanimated.cljs @@ -17,7 +17,9 @@ SlideInUp SlideOutUp LinearTransition - useAnimatedScrollHandler)] + useAnimatedScrollHandler + scrollTo + useAnimatedRef)] ["react-native-redash" :refer (withPause)] [react-native.flat-list :as rn-flat-list] [react-native.platform :as platform] @@ -49,11 +51,12 @@ (def fast-image (create-animated-component FastImage)) (def blur-view (if platform/ios? (create-animated-component (.-BlurView blur)) view)) +(def scroll-to scrollTo) ;; Hooks (def use-shared-value useSharedValue) (def use-animated-style useAnimatedStyle) (def use-animated-scroll-handler useAnimatedScrollHandler) - +(def use-animated-ref useAnimatedRef) ;; Animations (def with-timing withTiming) (def with-delay withDelay) diff --git a/src/status_im/contexts/communities/overview/style.cljs b/src/status_im/contexts/communities/overview/style.cljs index fd85cd0a239..716873bb408 100644 --- a/src/status_im/contexts/communities/overview/style.cljs +++ b/src/status_im/contexts/communities/overview/style.cljs @@ -1,42 +1,142 @@ (ns status-im.contexts.communities.overview.style (:require - [status-im.contexts.shell.constants :as shell.constants])) - -(def screen-horizontal-padding 20) - -(def last-community-tag - {:margin-right (* 2 screen-horizontal-padding)}) - -(def community-tag-container - {:padding-horizontal screen-horizontal-padding - :margin-horizontal (- screen-horizontal-padding) - :margin-bottom 16}) - -(def community-content-container - {:padding-horizontal screen-horizontal-padding}) + [quo.foundations.colors :as colors] + [react-native.core :as rn] + [react-native.safe-area :as safe-area])) (defn fetching-placeholder [top-inset] {:flex 1 :margin-top top-inset}) -(def blur-channel-header - {:position :absolute - :top 100 - :height 34 - :right 0 - :left 0 - :flex 1}) - (def community-overview-container - {:position :absolute - :top 0 - :left 0 - :right 0 - :bottom 0}) - -(defn channel-list-component - [] - {:margin-top 8 - :margin-bottom (+ 21 shell.constants/floating-shell-button-height) - :flex 1}) + {:flex 1}) + +(defn header-cover-image + [background-color] + {:width "100%" + :background-color background-color + :height (+ 20 ;; Area hidden by sheet on top but visible with rounded borders + 92 + (safe-area/get-top))}) + +(def cover-image {:flex 1}) + +(defn cover-image-blur-container + [header-opacity] + [rn/stylesheet-absolute-fill + {:opacity 0} + {:opacity header-opacity}]) + +(defn cover-image-blur-layer + [theme] + [rn/stylesheet-absolute-fill + {:background-color (colors/theme-colors colors/white-70-blur + colors/neutral-95-opa-70-blur + theme)}]) + +(def ^:private page-nav-container-base-style + {:height (+ 12 ;; padding-top + 12 ;; padding-bottom + 32) ;; button size + :width "100%"}) + +(defn page-nav-container + [opposite-header-opacity] + [rn/stylesheet-absolute-fill + page-nav-container-base-style + {:top (- (safe-area/get-top) 12) ;; -12 to place the button next to the safe-area + :opacity 1} + {:opacity opposite-header-opacity}]) + +(defn page-nav-container-blur + [header-opacity] + [rn/stylesheet-absolute-fill + page-nav-container-base-style + {:top (- (safe-area/get-top) 12) ;; -12 to place the button next to the safe-area + :opacity 0} + {:opacity header-opacity}]) + +(def community-logo + {:position :absolute + :z-index 1 + :width 88 + :height 88 + :border-radius 44 + :justify-content :center + :align-items :center + :background-color :white + :transform [{:translate-x 20} {:scale 1}] + :transform-origin "bottom left"}) + +(defn community-logo-bg-color + [theme] + {:background-color (colors/theme-colors colors/white + colors/neutral-95 + theme)}) + +(def community-logo-image + {:width 80 + :height 80 + :border-radius 40}) + +(defn community-info + [theme] + {:border-top-left-radius 20 + :border-top-right-radius 20 + :padding-top 44 + :background-color (colors/theme-colors colors/white colors/neutral-95 theme)}) + +(def status-tag-position + {:position :absolute :top 12 :right 12 :opacity 0}) + +(def community-name-and-description + {:padding-vertical 12 + :padding-horizontal 20 + :row-gap 8}) + +(def community-stats + {:flex-direction :row + :column-gap 12 + :height 22 + :padding-horizontal 20 + :opacity 0}) + +(def community-tags + {:margin-top 16 + :padding-horizontal 20 + :padding-bottom 20}) + +(def community-tags-last-item + {:margin-right (* 2 20)}) + +(defn request-to-join-button + [tags?] + {:padding-left 20 + :padding-right 20 + :padding-bottom 20 + :padding-top (when-not tags? 20)}) + +(def request-to-join-as + {:padding-left 20 + :padding-right 20 + :padding-top 4 + :padding-bottom 25}) + +(defn chanel-listing + [theme] + (let [height (- (:height (rn/get-window)) + (safe-area/get-top) + 32 + 11 + (safe-area/get-bottom))] + {:background-color (colors/theme-colors colors/white colors/neutral-95 theme) + :height height + :z-index 1})) + +(defn category-divider + [theme] + {:background-color (colors/theme-colors colors/white colors/neutral-95 theme)}) + +(def community-sheet-position + {:top (+ -20 -40)}) diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 1a7032530c2..5232b2a6665 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -1,96 +1,37 @@ (ns status-im.contexts.communities.overview.view (:require [oops.core :as oops] - [quo.context] [quo.core :as quo] - [quo.foundations.colors :as colors] + [quo.theme] [react-native.core :as rn] + [react-native.gesture :as gesture] + [react-native.platform :as platform] + [react-native.reanimated :as reanimated] [react-native.safe-area :as safe-area] - [reagent.core :as reagent] + [status-im.common.events-helper :as events.helper] [status-im.common.home.actions.view :as actions] [status-im.common.resources :as resources] - [status-im.common.scroll-page.style :as scroll-page.style] - [status-im.common.scroll-page.view :as scroll-page] [status-im.constants :as constants] - [status-im.contexts.communities.actions.chat.view :as chat-actions] [status-im.contexts.communities.actions.community-options.view :as options] [status-im.contexts.communities.overview.style :as style] [status-im.contexts.communities.utils :as communities.utils] [utils.debounce :as debounce] [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.worklets.communities :as worklets])) -(defn- add-category-height - [categories-heights category height] - (swap! categories-heights assoc category height)) +;; NOTE: values compared against `scroll-amount` to trigger animations. +(def expand-header-threshold 150) +(def sheet-displacement-threshold (+ expand-header-threshold 20)) +(def text-movement-threshold (* expand-header-threshold 0.7)) +(def info-opacity-threshold (* expand-header-threshold 0.5)) +(def expand-header-limit (+ sheet-displacement-threshold 56)) +(def snap-header-threshold (* expand-header-threshold 0.75)) (defn- collapse-category [community-id category-id collapsed?] - (rf/dispatch [:communities/toggle-collapsed-category community-id category-id (not collapsed?)])) - -(defn- layout-y - [event] - (oops/oget event "nativeEvent.layout.y")) - -(defn- channel-chat-item - [community-id - {:keys [name emoji muted? id mentions-count unread-messages? on-press locked? color] :as chat} - last-item?] - (let [sheet-content [actions/chat-actions - (assoc chat - :community-id community-id - :chat-type constants/community-chat-type - :chat-id (str community-id id)) - false] - notification (cond - muted? :mute - (> mentions-count 0) :mention - unread-messages? :notification - :else nil) - channel-options {:name name - :emoji emoji - :customization-color color - :mentions-count mentions-count - ;; NOTE: this is a troolean, nil/true/false have different meaning - :locked? locked? - :notification notification} - channel-sheet-data {:selected-item (fn [] [quo/channel channel-options]) - :content (fn [] sheet-content)}] - [rn/view {:key id :style (when last-item? {:margin-bottom 8})} - [quo/channel - (assoc channel-options - :on-press on-press - :on-long-press #(rf/dispatch [:show-bottom-sheet channel-sheet-data]))]])) - -(defn- channel-list-component - [{:keys [on-category-layout community-id on-first-channel-height-changed]} - channels-list] - [rn/view - {:on-layout #(on-first-channel-height-changed - (+ 38 (int (Math/ceil (layout-y %)))) - (into #{} (map (comp :name second) channels-list))) - :style (style/channel-list-component)} - (for [[category-id {:keys [chats name collapsed?]}] channels-list] - (when (seq chats) - [rn/view - {:key category-id - ;; on-layout fires only when the component re-renders, so - ;; in case the category hasn't changed, it will not be fired - :on-layout #(on-category-layout name category-id (int (layout-y %)))} - (when-not (= constants/empty-category-id category-id) - [quo/divider-label - {:on-press #(collapse-category community-id category-id collapsed?) - :chevron-icon (if collapsed? :i/chevron-right :i/chevron-down) - :chevron :left} - name]) - (when-not collapsed? - [rn/view {:style {:padding-horizontal 8}} - (let [last-item-index (dec (count chats))] - (map-indexed - (fn [index chat] - ^{:key (:id chat)} - [channel-chat-item community-id chat (= index last-item-index)]) - chats))])]))]) + (rf/dispatch + [:communities/toggle-collapsed-category community-id category-id (not collapsed?)])) (defn- get-access-type [access] @@ -100,20 +41,11 @@ constants/community-on-request-access :request-access :unknown-access)) -(defn- network-not-supported - [] - [quo/text (i18n/label :t/network-not-supported)]) - -(defn- request-access-button - [id color] - [quo/button - {:on-press #(rf/dispatch [:open-modal :community-account-selection-sheet - {:community-id id}]) - :accessibility-label :show-request-to-join-screen-button - :customization-color color - :container-style {:margin-bottom 12} - :icon-left :i/communities} - (i18n/label :t/request-to-join)]) +(defn- show-join-modal + [community-id] + (fn [] + (rf/dispatch [:open-modal :community-account-selection-sheet + {:community-id community-id}]))) (defn token-gated-communities-info [] @@ -121,218 +53,412 @@ [quo/text {:size :paragraph-2} (i18n/label :t/token-gated-communities-info)]]) -(defn- token-requirements - [{:keys [id color role-permissions?]}] - (let - [{:keys [can-request-access? no-member-permission? networks-not-supported? - highest-permission-role - tokens]} (rf/sub [:community/token-gated-overview id]) - highest-role-text (i18n/label - (communities.utils/role->translation-key highest-permission-role - :t/member)) - on-press (rn/use-callback - (fn [] - (rf/dispatch [:open-modal :community-account-selection-sheet - {:community-id id}])) - [id]) - on-press-info #(rf/dispatch - [:show-bottom-sheet {:content token-gated-communities-info}])] +(defn- on-join-info-press + [] + (rf/dispatch [:show-bottom-sheet {:content token-gated-communities-info}])) +(defn- token-requirements + [community-id role-permissions? color tags?] + (let [{:keys [can-request-access? no-member-permission? networks-not-supported? + highest-permission-role + tokens]} (rf/sub [:community/token-gated-overview community-id]) + on-request-access-press (show-join-modal community-id)] (cond networks-not-supported? - [network-not-supported] + [rn/view {:style (style/request-to-join-button tags?)} + [quo/text (i18n/label :t/network-not-supported)]] (or (not role-permissions?) no-member-permission?) - [request-access-button id color] + [rn/view {:style (style/request-to-join-button tags?)} + [quo/button + {:on-press on-request-access-press + :accessibility-label :show-request-to-join-screen-button + :customization-color color + :icon-left :i/communities} + (i18n/label :t/request-to-join)]] :else - [quo/community-token-gating - {:role highest-role-text - :tokens tokens - :community-color color - :satisfied? can-request-access? - :on-press on-press - :on-press-info on-press-info}]))) + (let [highest-role-text (i18n/label + (communities.utils/role->translation-key + highest-permission-role + :t/member))] + [rn/view {:style style/request-to-join-as} + [quo/community-token-gating + {:role highest-role-text + :tokens tokens + :community-color color + :satisfied? can-request-access? + :on-press on-request-access-press + :on-press-info on-join-info-press}]])))) (defn- join-community - [{:keys [id joined permissions] :as community}] - (let [pending? (rf/sub [:communities/my-pending-request-to-join id]) - access-type (get-access-type (:access permissions)) - unknown-access? (= access-type :unknown-access) - invite-only? (= access-type :invite-only)] - (when-not (or joined pending? invite-only? unknown-access?) - [token-requirements community]))) + [{:keys [community-id joined? permissions role-permissions? color tags?]}] + (let [pending? (rf/sub [:communities/my-pending-request-to-join community-id]) + access-type (get-access-type (:access permissions))] + (when-not (or joined? pending? (#{:unknown-access :invite-only} access-type)) + [token-requirements community-id role-permissions? color tags?]))) (defn- status-tag - [community-id joined] + [{:keys [community-id joined? info-styles]}] (let [pending? (rf/sub [:communities/my-pending-request-to-join community-id])] - (when (or pending? joined) - [rn/view {:style {:position :absolute :top 12 :right 12}} + (when (or pending? joined?) + [reanimated/view {:style [style/status-tag-position info-styles]} [quo/status-tag - {:status {:type (if joined :positive :pending)} - :label (if joined - (i18n/label :t/joined) - (i18n/label :t/pending))}]]))) + {:status {:type (if joined? :positive :pending)} + :label (if joined? (i18n/label :t/joined) (i18n/label :t/pending))}]]))) -(defn- add-handlers +(defn- category-divider [community-id - joined-or-spectated - {:keys [id locked?] - :or {locked? false} - :as chat}] - (cond-> chat - (and (not locked?) id) - (assoc :on-press (when joined-or-spectated - (fn [] - (rf/dispatch [:dismiss-keyboard]) - (debounce/throttle-and-dispatch - [:communities/navigate-to-community-chat (str community-id id)] - 1000))) - :on-long-press #(rf/dispatch - [:show-bottom-sheet - {:content (fn [] - [chat-actions/actions chat false])}]) - :community-id community-id))) - -(defn- add-handlers-to-chats - [community-id joined-or-spectated chats] - (mapv (partial add-handlers community-id joined-or-spectated) chats)) - -(defn- add-handlers-to-categorized-chats - [community-id categorized-chats joined-or-spectated] - (let [add-on-press (partial add-handlers-to-chats community-id joined-or-spectated)] - (map (fn [[category v]] - [category (update v :chats add-on-press)]) - categorized-chats))) - -(defn- community-header - [title logo description] - [quo/text-combinations - {:container-style {:margin-top - (if logo - 12 - (+ scroll-page.style/picture-radius - scroll-page.style/picture-border-width - 12)) - :margin-bottom 12} - :avatar logo - :title title - :title-number-of-lines 2 - :description description - :title-accessibility-label :community-title - :description-accessibility-label :community-description}]) - -(defn- community-content - [id {:keys [on-category-layout collapsed? on-first-channel-height-changed]}] - (let [{:keys [name description joined spectated images tags id membership-permissions?] - :as community} (rf/sub [:communities/community id]) - joined-or-spectated (or joined spectated) - chats-by-category (rf/sub [:communities/categorized-channels id])] + {collapsed? :collapsed? + category-name :name + category-id :id}] + (let [theme (quo.theme/use-theme)] + [rn/view + {:style (style/category-divider theme) + :blur-amount 20 + :blur-type :transparent + :overlay-color :transparent} + [quo/divider-label + {:on-press (fn [] (collapse-category community-id category-id collapsed?)) + :chevron-icon (if collapsed? :i/chevron-right :i/chevron-down) + :chevron :left + :blur? true} + category-name]])) + +(defn- notification-type + [{:keys [muted? mentions-count unread-messages?] :as _chat}] + (cond + muted? :mute + (> mentions-count 0) :mention + unread-messages? :notification)) + +(defn- navigate-to-chat + [chat-id] + (rf/dispatch [:dismiss-keyboard]) + (debounce/throttle-and-dispatch + [:communities/navigate-to-community-chat chat-id] + 1000)) + +(defn- show-chat-actions + [chat-data] + (rf/dispatch + [:show-bottom-sheet + {:selected-item (fn [] [quo/channel chat-data]) + :content (fn [] [actions/chat-actions chat-data false])}])) + +(defn channel-item + [{:keys [color locked?] + channel-id :id + :as chat} + {:keys [community-id joined-or-spectated?] :as _community-data}] + [rn/view {:style {:padding-horizontal 8}} + (let [chat-id (str community-id channel-id) + chat-data (assoc chat + :community-id community-id + :chat-type constants/community-chat-type + :chat-id chat-id + :customization-color color + :notification (notification-type chat)) + on-press (rn/use-callback + (fn [] + (when (and (not locked?) channel-id joined-or-spectated?) + (navigate-to-chat chat-id))) + [joined-or-spectated? locked? channel-id]) + on-long-press (rn/use-callback + (fn [] + (when (and (not locked?) channel-id) + (show-chat-actions chat-data))) + [locked? channel-id])] + [quo/channel + (assoc chat-data + :on-press on-press + :on-long-press on-long-press)])]) + +(defn channel-listing-item + [{:keys [community-id] :as community-data}] + (fn [{:keys [render-as] :as item-data} _ _ _] + (case render-as + :separator [rn/view {:style {:height 8}}] + :category [category-divider community-id item-data] + :channel [channel-item item-data community-data] + nil))) + +(def channel-component-heights + {:category 34 + :channel 48 + :separator 8}) + +(defn- calc-scrollable-content + [scrollable-area] + (+ scrollable-area + (safe-area/get-top) + 32 + 12 ;; top spacing + (safe-area/get-bottom) + (- (:height (rn/get-window))))) + +(defn- channel-listing + [{:keys [community-id scroll-amount header-height set-max-scroll]}] + (let [theme (quo.theme/use-theme) + channels-styles (worklets/use-channels-styles + #js {:scrollAmount scroll-amount + :headerHeight header-height + :expandHeaderThreshold expand-header-threshold + :sheetDisplacementThreshold sheet-displacement-threshold + :expandHeaderLimit expand-header-limit}) + flat-list-ref (reanimated/use-animated-ref) + _ (worklets/use-scroll-to + #js {:animatedRef flat-list-ref + :scrollAmount scroll-amount + :expandHeaderLimit expand-header-limit}) + community (rf/sub [:communities/community community-id]) + joined-or-spectated? (or (:joined community) (:spectated community)) + render-fn (rn/use-callback + (channel-listing-item {:community-id community-id + :joined-or-spectated? joined-or-spectated?}) + [joined-or-spectated?]) + flatten-channels (rf/sub [:communities/flatten-channels-and-categories community-id]) + categories-indexes (keep-indexed (fn [idx {:keys [render-as]}] + (when (= render-as :category) + idx)) + flatten-channels) + scrollable-area-height (->> flatten-channels + (map (comp channel-component-heights :render-as)) + (reduce +))] + (rn/use-effect + (fn [] + (let [max-scroll-offset (calc-scrollable-content scrollable-area-height)] + (if (neg? max-scroll-offset) + (set-max-scroll 0) + (set-max-scroll max-scroll-offset)))) + [scrollable-area-height]) + [reanimated/flat-list + {:ref flat-list-ref + :style [(style/chanel-listing theme) channels-styles] + :data flatten-channels + :content-container-style (when platform/ios? + {:padding-bottom (safe-area/get-bottom)}) + :sticky-header-indices categories-indexes + :scroll-enabled false + :render-fn render-fn + :key-fn :id}])) + + +(defn- header-cover-image + [{:keys [cover-image background-color header-opacity]}] + (let [theme (quo.theme/use-theme)] + [rn/view {:style (style/header-cover-image background-color)} + [reanimated/image {:style style/cover-image :source {:uri cover-image}}] + [reanimated/view {:style (style/cover-image-blur-container header-opacity)} + [rn/image + {:style style/cover-image + :source {:uri cover-image} + :blur-radius 20}] + [rn/view {:style (style/cover-image-blur-layer theme)}]]])) + +(defn- open-community-options + [community-id] + (fn [] + (rf/dispatch + [:show-bottom-sheet + {:content (fn [] [options/community-options-bottom-sheet community-id])}]))) + +(defn- page-nav + [{:keys [blur-version? nav-content-opacity community-name community-logo community-id]}] + (let [on-options-press (rn/use-callback (open-community-options community-id)) + base-props {:right-side [{:icon-name :i/options + :accessibility-label :community-options-for-community + :on-press on-options-press}] + :icon-name :i/close + :on-press events.helper/navigate-back + :accessibility-label :back-button}] + (if blur-version? + [quo/page-nav + (assoc base-props + :type :community + :background :blur + :center-opacity nav-content-opacity + :community-name community-name + :community-logo community-logo)] + [quo/page-nav + (assoc base-props + :type :no-title + :background :photo)]))) + +(defn- header + [community-id scroll-amount] + (let [header-opacity (worklets/use-header-opacity + #js {:scrollAmount scroll-amount + :expandHeaderThreshold expand-header-threshold + :sheetDisplacementThreshold sheet-displacement-threshold}) + opposite-header-opacity (worklets/use-opposite-header-opacity header-opacity) + nav-content-opacity (worklets/use-nav-content-opacity + #js {:scrollAmount scroll-amount + :sheetDisplacementThreshold sheet-displacement-threshold + :expandHeaderLimit expand-header-limit}) + community (rf/sub [:communities/community community-id])] [:<> - [rn/view {:style style/community-content-container} - (when-not collapsed? - [status-tag id joined]) - [community-header name (when collapsed? (get-in images [:thumbnail :uri])) - (when-not collapsed? description)] - (when (and (seq tags) (not collapsed?)) - [quo/community-tags - {:tags tags - :last-item-style style/last-community-tag - :container-style style/community-tag-container}]) - [join-community community]] - (when (or joined (not membership-permissions?)) - [channel-list-component - {:on-category-layout on-category-layout - :community-id id - :on-first-channel-height-changed on-first-channel-height-changed} - (add-handlers-to-categorized-chats id chats-by-category joined-or-spectated)])])) - -(defn- sticky-category-header - [_] - (fn [{:keys [enabled label]}] - (when enabled - [quo/blur - {:style style/blur-channel-header - :blur-amount 20 - :blur-type :transparent - :overlay-color :transparent} - [quo/divider-label - {:chevron :left} - label]]))) - -(defn- page-nav-right-section-buttons - [id] - [{:icon-name :i/options - :accessibility-label :community-options-for-community - :on-press #(rf/dispatch - [:show-bottom-sheet - {:content (fn [] [options/community-options-bottom-sheet id])}])}]) - -(defn- pick-first-category-by-height - [scroll-height first-channel-height categories-heights] - (->> categories-heights - (sort-by (comp - second)) - (some (fn [[category height]] - (and (>= scroll-height (+ height first-channel-height)) - category))))) - - ;; We track the initial value of joined - ;; as we open the page to avoid switching - ;; from not collapsed to collapsed if the - ;; user is on this page - -(defn- community-scroll-page - [_ initial-joined? _ _] - (let [scroll-height (reagent/atom 0) - categories-heights (reagent/atom {}) - first-channel-height (reagent/atom 0) - on-category-layout (partial add-category-height categories-heights) - on-first-channel-height-changed (fn [height categories] - (swap! categories-heights select-keys categories) - (reset! first-channel-height height))] - (fn [id joined name images] - (let [theme (quo.context/use-theme) - cover {:uri (get-in images [:banner :uri])} - logo {:uri (get-in images [:large :uri])} - collapsed? (and initial-joined? joined) - first-category-height (->> @categories-heights - vals - (apply min) - (+ @first-channel-height)) - overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))] - [scroll-page/scroll-page - {:cover-image cover - :collapsed? collapsed? - :logo logo - :name name - :on-scroll #(reset! scroll-height %) - :navigate-back? true - :height 148 - :overlay-shown? overlay-shown? - :background-color (colors/theme-colors colors/white colors/neutral-95 theme) - :page-nav-props {:type :community - :right-side (page-nav-right-section-buttons id) - :community-name name - :community-logo logo} - :sticky-header [sticky-category-header - {:enabled (> @scroll-height - first-category-height) - :label (pick-first-category-by-height - @scroll-height - @first-channel-height - @categories-heights)}]} - [community-content - id - {:on-category-layout on-category-layout - :collapsed? collapsed? - :on-first-channel-height-changed - ;; Here we set the height of the component and we filter out the categories, as some - ;; might have been removed. - on-first-channel-height-changed}]])))) + [header-cover-image + {:cover-image (-> community :images :banner :uri) + :background-color (:color community) + :header-opacity header-opacity}] + [reanimated/view {:style (style/page-nav-container opposite-header-opacity)} + [page-nav + {:blur-version? false + :community-id community-id}]] + [reanimated/view {:style (style/page-nav-container-blur header-opacity)} + [page-nav + {:blur-version? true + :community-id community-id + :nav-content-opacity nav-content-opacity + :community-name (:name community) + :community-logo (-> community :images :large :uri)}]]])) + +(defn- community-logo + [{:keys [scroll-amount community-id]}] + (let [theme (quo.theme/use-theme) + logo-styles (worklets/use-logo-styles + #js {:scrollAmount scroll-amount + :expandHeaderThreshold expand-header-threshold + :sheetDisplacementThreshold sheet-displacement-threshold + :textMovementThreshold text-movement-threshold}) + logo (-> (rf/sub [:communities/community community-id]) :images :large :uri)] + [reanimated/view + {:style [style/community-logo + (style/community-logo-bg-color theme) + logo-styles]} + [rn/image {:style style/community-logo-image :source logo}]])) + +(defn- name-and-description + [{:keys [scroll-amount community-name community-description info-styles]}] + (let [name-styles (worklets/use-name-styles + #js {:scrollAmount scroll-amount + :expandHeaderThreshold expand-header-threshold + :textMovementThreshold text-movement-threshold})] + [rn/view {:style style/community-name-and-description} + [reanimated/view {:style name-styles} + [quo/text {:weight :semi-bold :size :heading-1 :number-of-lines 1} + community-name]] + [reanimated/view {:style [{:opacity 0} info-styles]} + [quo/text {:weight :regular :size :paragraph-1} + community-description]]])) + +(defn- community-info-tags + [community-tags info-styles] + (when (seq community-tags) + [reanimated/view {:style info-styles} + [quo/community-tags + {:tags community-tags + :last-item-style style/community-tags-last-item + :container-style style/community-tags}]])) + +(defn- community-info-stats + [{:keys [members-count active-members-count info-styles]}] + [reanimated/view {:style [style/community-stats info-styles]} + [rn/view {:style {:flex-direction :row :column-gap 12}} + [quo/community-stat + {:accessibility-label :stats-members-count + :icon :i/group + :value members-count}] + [quo/community-stat + {:accessibility-label :stats-active-count + :icon :i/active-members + :value active-members-count}]]]) + +(defn- community-info + [{:keys [scroll-amount header-height community-id]}] + (let [theme (quo.theme/use-theme) + sheet-styles (worklets/use-sheet-styles + #js {:scrollAmount scroll-amount + :expandHeaderThreshold expand-header-threshold + :sheetDisplacementThreshold sheet-displacement-threshold}) + info-styles (worklets/use-info-styles + #js {:scrollAmount scroll-amount + :infoOpacityThreshold info-opacity-threshold}) + set-header-height (rn/use-callback + (fn [e] + (let [height (oops/oget e "nativeEvent.layout.height")] + (reanimated/set-shared-value header-height (or height 0))))) + community (rf/sub [:communities/community community-id]) + members-count (count (js-keys (:members community)))] + [reanimated/view + {:style [(style/community-info theme) sheet-styles] + :on-layout set-header-height} + [status-tag + {:community-id community-id + :joined? (:joined community) + :info-styles info-styles}] + [name-and-description + {:scroll-amount scroll-amount + :community-name (:name community) + :community-description (:description community) + :info-styles info-styles}] + [community-info-stats + {:members-count members-count + :active-members-count (:activeMembersCount community) + :info-styles info-styles}] + [community-info-tags (:tags community) info-styles] + [join-community + {:community-id community-id + :joined? (:joined community) + :tags? (seq (:tags community)) + :permissions (:permissions community) + :role-permissions? (:role-permissions? community) + :color (:color community)}]])) + +(defn- community-sheet + [{:keys [community-id scroll-amount set-max-scroll]}] + (let [header-height (reanimated/use-shared-value 0)] + [rn/view {:style style/community-sheet-position} + [community-logo + {:community-id community-id + :scroll-amount scroll-amount}] + [community-info + {:scroll-amount scroll-amount + :header-height header-height + :community-id community-id}] + [channel-listing + {:community-id community-id + :scroll-amount scroll-amount + :header-height header-height + :set-max-scroll set-max-scroll}]])) + +(defn- community-overview + [community-id expanded?] + (let [max-scroll (reanimated/use-shared-value 0) + set-max-scroll (rn/use-callback + (fn [max-scroll-amount] + (reanimated/set-shared-value max-scroll max-scroll-amount))) + scroll-start (reanimated/use-shared-value (if expanded? 0 (- expand-header-threshold))) + scroll-amount (reanimated/use-shared-value (if expanded? 0 expand-header-threshold)) + on-pan-start (worklets/on-pan-start scroll-start scroll-amount) + on-pan-update (worklets/on-pan-update + #js {:scrollStart scroll-start + :scrollAmount scroll-amount + :maxScroll max-scroll + :expandHeaderLimit expand-header-limit}) + on-pan-end (worklets/on-pan-end + #js {:scrollStart scroll-start + :scrollAmount scroll-amount + :maxScroll max-scroll + :expandHeaderLimit expand-header-limit + :expandHeaderThreshold expand-header-threshold + :snapHeaderThreshold snap-header-threshold}) + pan-gesture (-> (gesture/gesture-pan) + (gesture/on-start on-pan-start) + (gesture/on-update on-pan-update) + (gesture/on-end on-pan-end))] + [gesture/gesture-detector {:gesture pan-gesture} + [rn/view {:style {:flex 1}} + [header community-id scroll-amount] + [community-sheet + {:community-id community-id + :scroll-amount scroll-amount + :set-max-scroll set-max-scroll}]]])) (defn- community-fetching-placeholder [id] - (let [theme (quo.context/use-theme) + (let [theme (quo.theme/use-theme) top-inset (safe-area/get-top) fetching? (rf/sub [:communities/fetching-community id])] [rn/view @@ -354,16 +480,12 @@ (i18n/label :t/failed-to-fetch-community)) :container-style {:flex 1 :justify-content :center}}]])) -(defn- community-card-page-view - [id] - (let [{:keys [joined name images] - :as community} (rf/sub [:communities/community id])] - (if community - [community-scroll-page id joined name images] - [community-fetching-placeholder id]))) - (defn view [id] - (let [id (or id (quo.context/use-screen-params))] + (let [community-id (or id (rf/sub [:get-screen-params :community-overview])) + community (rf/sub [:communities/community community-id]) + start-expanded? (not (:joined community))] [rn/view {:style style/community-overview-container} - [community-card-page-view id]])) + (if community + [community-overview community-id start-expanded?] + [community-fetching-placeholder community-id])])) diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index 06322c06a83..8e82bd86a4c 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -364,6 +364,45 @@ %)))])))] categories-and-chats))) +(def ^:private channel-separator {:render-as :separator}) + +(defn- mark-as-category + ([category] + (assoc (dissoc category :chats) :render-as :category)) + ([category category-id] + (let [render-as (if (= category-id :communities/not-categorized) :nothing :category)] + (assoc (dissoc category :chats) + :render-as + render-as)))) + +(defn- mark-as-channel + [channel] + (assoc channel :render-as :channel)) + +(re-frame/reg-sub + :communities/flatten-channels-and-categories + (fn [[_ community-id]] + (re-frame/subscribe [:communities/categorized-channels community-id])) + (fn [categorized-channels [_ _community-id]] + (mapcat (fn [[category-id category]] + (when (seq (:chats category)) + (if (:collapsed? category) + [(mark-as-category category)] + (concat [(mark-as-category category category-id)] + (map mark-as-channel (:chats category)) + [channel-separator])))) + categorized-channels))) + +(re-frame/reg-sub + :communities + (fn [[_ community-id]] + (re-frame/subscribe [:communities/flatten-channels-and-categories community-id])) + (fn [flatten-channels-and-categories [_ _community-id]] + (keep-indexed (fn [idx {:keys [render-as]}] + (when (= render-as :category) + idx)) + flatten-channels-and-categories))) + (re-frame/reg-sub :communities/collapsed-categories-for-community :<- [:communities/collapsed-categories] diff --git a/src/utils/worklets/communities.cljs b/src/utils/worklets/communities.cljs new file mode 100644 index 00000000000..7b3b084e6d6 --- /dev/null +++ b/src/utils/worklets/communities.cljs @@ -0,0 +1,17 @@ +(ns utils.worklets.communities) + +(def worklets (js/require "../src/js/worklets/communities.js")) + +(def use-logo-styles (.-useLogoStyles worklets)) +(def use-sheet-styles (.-useSheetStyles worklets)) +(def use-name-styles (.-useNameStyles worklets)) +(def use-info-styles (.-useInfoStyles worklets)) +(def use-channels-styles (.-useChannelsStyles worklets)) +(def use-scroll-to (.-useScrollTo worklets)) +(def use-header-opacity (.-useHeaderOpacity worklets)) +(def use-opposite-header-opacity (.-useOppositeHeaderOpacity worklets)) +(def use-nav-content-opacity (.-useNavContentOpacity worklets)) + +(def on-pan-start (.-onPanStart worklets)) +(def on-pan-update (.-onPanUpdate worklets)) +(def on-pan-end (.-onPanEnd worklets)) From dfa0cf88cdee7c05753462af4655d91b1bf88f43 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 13 Mar 2025 14:40:39 -0600 Subject: [PATCH 03/16] Add mock for communities --- src/mocks/js_dependencies.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index b0cf25893e9..0e0c26e4d0c 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -429,6 +429,7 @@ (slurp "./resources/data/emojis/en.json")) "../src/js/worklets/core.js" worklet-factory + "../src/js/worklets/communities.js" #js {} "../src/js/worklets/shell/bottom_tabs.js" #js {} "../src/js/worklets/shell/home_stack.js" #js {} "../src/js/worklets/bottom_sheet.js" #js {} From 64948261da71fe709982d1f8b4d4263bbb0d00e7 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 18 Mar 2025 14:15:57 -0600 Subject: [PATCH 04/16] Fix typo --- src/status_im/contexts/communities/overview/style.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/status_im/contexts/communities/overview/style.cljs b/src/status_im/contexts/communities/overview/style.cljs index 716873bb408..39142b5a7b7 100644 --- a/src/status_im/contexts/communities/overview/style.cljs +++ b/src/status_im/contexts/communities/overview/style.cljs @@ -123,7 +123,7 @@ :padding-top 4 :padding-bottom 25}) -(defn chanel-listing +(defn channel-listing [theme] (let [height (- (:height (rn/get-window)) (safe-area/get-top) From a9de2e2246055d2a8742458078a1bc7cf65a2b22 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 18 Mar 2025 15:52:51 -0600 Subject: [PATCH 05/16] PR comments 1 --- .../contexts/communities/overview/style.cljs | 13 +-- .../contexts/communities/overview/view.cljs | 87 ++++++++++--------- src/status_im/subs/chats.cljs | 1 - src/status_im/subs/communities.cljs | 64 ++++++++------ 4 files changed, 89 insertions(+), 76 deletions(-) diff --git a/src/status_im/contexts/communities/overview/style.cljs b/src/status_im/contexts/communities/overview/style.cljs index 39142b5a7b7..ce4cac4a59c 100644 --- a/src/status_im/contexts/communities/overview/style.cljs +++ b/src/status_im/contexts/communities/overview/style.cljs @@ -124,15 +124,10 @@ :padding-bottom 25}) (defn channel-listing - [theme] - (let [height (- (:height (rn/get-window)) - (safe-area/get-top) - 32 - 11 - (safe-area/get-bottom))] - {:background-color (colors/theme-colors colors/white colors/neutral-95 theme) - :height height - :z-index 1})) + [theme height] + {:background-color (colors/theme-colors colors/white colors/neutral-95 theme) + :height height + :z-index 1}) (defn category-divider [theme] diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 5232b2a6665..acb4fc15ec9 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -188,14 +188,17 @@ :channel 48 :separator 8}) -(defn- calc-scrollable-content - [scrollable-area] - (+ scrollable-area - (safe-area/get-top) - 32 - 12 ;; top spacing - (safe-area/get-bottom) - (- (:height (rn/get-window))))) +(defn- unusable-area-height [] + (+ (safe-area/get-top) + 32 11 ;;top page buttons & button's padding + (safe-area/get-bottom))) + +(defn- calc-scrollable-content [scrollable-height] + (- (+ scrollable-height (unusable-area-height)) + (:height (rn/get-window)))) + +(defn- calc-listing-height [] + (- (:height (rn/get-window)) (unusable-area-height))) (defn- channel-listing [{:keys [community-id scroll-amount header-height set-max-scroll]}] @@ -207,24 +210,25 @@ :sheetDisplacementThreshold sheet-displacement-threshold :expandHeaderLimit expand-header-limit}) flat-list-ref (reanimated/use-animated-ref) - _ (worklets/use-scroll-to - #js {:animatedRef flat-list-ref - :scrollAmount scroll-amount - :expandHeaderLimit expand-header-limit}) - community (rf/sub [:communities/community community-id]) - joined-or-spectated? (or (:joined community) (:spectated community)) + _scroll-to-animation (worklets/use-scroll-to + #js {:animatedRef flat-list-ref + :scrollAmount scroll-amount + :expandHeaderLimit expand-header-limit}) + {:keys [joined? + spectated?]} (rf/sub [:communities/community-overview community-id]) + joined-or-spectated? (or joined? spectated?) render-fn (rn/use-callback (channel-listing-item {:community-id community-id :joined-or-spectated? joined-or-spectated?}) [joined-or-spectated?]) flatten-channels (rf/sub [:communities/flatten-channels-and-categories community-id]) categories-indexes (keep-indexed (fn [idx {:keys [render-as]}] - (when (= render-as :category) - idx)) + (when (= render-as :category) idx)) flatten-channels) scrollable-area-height (->> flatten-channels (map (comp channel-component-heights :render-as)) - (reduce +))] + (reduce +)) + listing-height (calc-listing-height)] (rn/use-effect (fn [] (let [max-scroll-offset (calc-scrollable-content scrollable-area-height)] @@ -234,16 +238,14 @@ [scrollable-area-height]) [reanimated/flat-list {:ref flat-list-ref - :style [(style/chanel-listing theme) channels-styles] + :style [(style/channel-listing theme listing-height) channels-styles] :data flatten-channels - :content-container-style (when platform/ios? - {:padding-bottom (safe-area/get-bottom)}) + :content-container-style (when platform/ios? {:padding-bottom (safe-area/get-bottom)}) :sticky-header-indices categories-indexes :scroll-enabled false :render-fn render-fn :key-fn :id}])) - (defn- header-cover-image [{:keys [cover-image background-color header-opacity]}] (let [theme (quo.theme/use-theme)] @@ -296,11 +298,12 @@ #js {:scrollAmount scroll-amount :sheetDisplacementThreshold sheet-displacement-threshold :expandHeaderLimit expand-header-limit}) - community (rf/sub [:communities/community community-id])] + {:keys [community-name color logo + cover-image]} (rf/sub [:communities/community-overview community-id])] [:<> [header-cover-image - {:cover-image (-> community :images :banner :uri) - :background-color (:color community) + {:cover-image cover-image + :background-color color :header-opacity header-opacity}] [reanimated/view {:style (style/page-nav-container opposite-header-opacity)} [page-nav @@ -311,8 +314,8 @@ {:blur-version? true :community-id community-id :nav-content-opacity nav-content-opacity - :community-name (:name community) - :community-logo (-> community :images :large :uri)}]]])) + :community-name community-name + :community-logo logo}]]])) (defn- community-logo [{:keys [scroll-amount community-id]}] @@ -322,7 +325,7 @@ :expandHeaderThreshold expand-header-threshold :sheetDisplacementThreshold sheet-displacement-threshold :textMovementThreshold text-movement-threshold}) - logo (-> (rf/sub [:communities/community community-id]) :images :large :uri)] + {:keys [logo]} (rf/sub [:communities/community-overview community-id])] [reanimated/view {:style [style/community-logo (style/community-logo-bg-color theme) @@ -379,32 +382,34 @@ (fn [e] (let [height (oops/oget e "nativeEvent.layout.height")] (reanimated/set-shared-value header-height (or height 0))))) - community (rf/sub [:communities/community community-id]) - members-count (count (js-keys (:members community)))] + {:keys [community-name description active-members-count tags role-permissions? + permissions color + joined?]} (rf/sub [:communities/community-overview community-id]) + members-count (count (rf/sub [:communities/community-members community-id]))] [reanimated/view {:style [(style/community-info theme) sheet-styles] :on-layout set-header-height} [status-tag {:community-id community-id - :joined? (:joined community) + :joined? joined? :info-styles info-styles}] [name-and-description {:scroll-amount scroll-amount - :community-name (:name community) - :community-description (:description community) + :community-name community-name + :community-description description :info-styles info-styles}] [community-info-stats {:members-count members-count - :active-members-count (:activeMembersCount community) + :active-members-count active-members-count :info-styles info-styles}] - [community-info-tags (:tags community) info-styles] + [community-info-tags tags info-styles] [join-community {:community-id community-id - :joined? (:joined community) - :tags? (seq (:tags community)) - :permissions (:permissions community) - :role-permissions? (:role-permissions? community) - :color (:color community)}]])) + :joined? joined? + :tags? (seq tags) + :permissions permissions + :role-permissions? role-permissions? + :color color}]])) (defn- community-sheet [{:keys [community-id scroll-amount set-max-scroll]}] @@ -483,8 +488,8 @@ (defn view [id] (let [community-id (or id (rf/sub [:get-screen-params :community-overview])) - community (rf/sub [:communities/community community-id]) - start-expanded? (not (:joined community))] + community (rf/sub [:communities/community-overview community-id]) + start-expanded? (:joined? community)] [rn/view {:style style/community-overview-container} (if community [community-overview community-id start-expanded?] diff --git a/src/status_im/subs/chats.cljs b/src/status_im/subs/chats.cljs index caf1a24bbfd..f5f427512e3 100644 --- a/src/status_im/subs/chats.cljs +++ b/src/status_im/subs/chats.cljs @@ -140,7 +140,6 @@ (get-in community [:chats relative-chat-id :can-post?])) (assoc :able-to-send-message? true) - (and (chat.events/group-chat? current-chat) (member? my-public-key current-chat)) (assoc :able-to-send-message? true diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index 8e82bd86a4c..ce0144c013d 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -69,9 +69,9 @@ (re-frame/reg-sub :communities/community-members (fn [[_ community-id]] - [(re-frame/subscribe [:communities/community community-id])]) - (fn [[{:keys [members]}] _] - (js-keys members))) + (re-frame/subscribe [:communities/community community-id])) + (fn [community _] + (js-keys (:members community)))) (re-frame/reg-sub :communities/community-chat-members @@ -364,44 +364,59 @@ %)))])))] categories-and-chats))) -(def ^:private channel-separator {:render-as :separator}) +(def ^:private channel-separator-item [{:render-as :separator}]) -(defn- mark-as-category +(defn- get-category-item ([category] - (assoc (dissoc category :chats) :render-as :category)) + (get-category-item category nil)) ([category category-id] (let [render-as (if (= category-id :communities/not-categorized) :nothing :category)] - (assoc (dissoc category :chats) - :render-as - render-as)))) + (-> category + (dissoc :chats) + (assoc :render-as render-as) + vector)))) (defn- mark-as-channel [channel] (assoc channel :render-as :channel)) +(defn- category-with-channels + [category-id {:keys [chats] :as category}] + (let [category-item (get-category-item category category-id) + channels (map mark-as-channel chats)] + (concat category-item channels channel-separator-item))) + (re-frame/reg-sub :communities/flatten-channels-and-categories (fn [[_ community-id]] (re-frame/subscribe [:communities/categorized-channels community-id])) (fn [categorized-channels [_ _community-id]] - (mapcat (fn [[category-id category]] - (when (seq (:chats category)) - (if (:collapsed? category) - [(mark-as-category category)] - (concat [(mark-as-category category category-id)] - (map mark-as-channel (:chats category)) - [channel-separator])))) - categorized-channels))) + (mapcat (fn [[category-id {:keys [collapsed? chats] :as category}]] + (when (seq chats) + (if collapsed? + (get-category-item category) + (category-with-channels category-id category)))) + categorized-channels))) (re-frame/reg-sub - :communities + :communities/community-overview (fn [[_ community-id]] - (re-frame/subscribe [:communities/flatten-channels-and-categories community-id])) - (fn [flatten-channels-and-categories [_ _community-id]] - (keep-indexed (fn [idx {:keys [render-as]}] - (when (= render-as :category) - idx)) - flatten-channels-and-categories))) + (re-frame/subscribe [:communities/community community-id])) + (fn [{:keys [joined spectated images description color activeMembersCount tags + permissions role-permissions?] + :as community}] + (when community + {:joined? joined + :spectated? spectated + :cover-image (-> images :banner :uri) + :logo (-> images :large :uri) + :community-name (:name community) + :description description + :color color + :active-members-count activeMembersCount + :tags tags + :permissions permissions + :role-permissions? role-permissions?}))) (re-frame/reg-sub :communities/collapsed-categories-for-community @@ -409,7 +424,6 @@ (fn [collapsed-categories [_ community-id]] (get collapsed-categories community-id))) - (defn token-requirement->token [checking-permissions? token-images From 4db042801979843f38cd67871bf8694ab5cc64d4 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 18 Mar 2025 16:59:47 -0600 Subject: [PATCH 06/16] Add a worklet wrapper to use kebab-case keywords --- src/react_native/utils.cljs | 16 ++++- .../contexts/communities/overview/view.cljs | 72 +++++++++---------- src/utils/transforms.cljs | 1 + src/utils/worklets/communities.cljs | 40 +++++++---- 4 files changed, 79 insertions(+), 50 deletions(-) diff --git a/src/react_native/utils.cljs b/src/react_native/utils.cljs index 79f3f72ab4c..c68ade61e08 100644 --- a/src/react_native/utils.cljs +++ b/src/react_native/utils.cljs @@ -1,4 +1,6 @@ -(ns react-native.utils) +(ns react-native.utils + (:require [goog.object :as gobj] + [utils.transforms :as transforms])) (defonce ^:private throttle (atom {})) @@ -37,3 +39,15 @@ props (when (map? first-child) first-child) children (if props (rest argv) argv)] [props children])) + +(defn kebab-case-map->camelCase-obj + "Takes a Clojure map with kebab-case keys and returns a JS object with camelCase keys. + Not recursive" + [m] + (if (map? m) + (reduce-kv (fn [o k v] + (doto o + (gobj/set (transforms/->camelCaseString k) v))) + #js{} + m) + m)) diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index acb4fc15ec9..e278ff8477a 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -204,16 +204,16 @@ [{:keys [community-id scroll-amount header-height set-max-scroll]}] (let [theme (quo.theme/use-theme) channels-styles (worklets/use-channels-styles - #js {:scrollAmount scroll-amount - :headerHeight header-height - :expandHeaderThreshold expand-header-threshold - :sheetDisplacementThreshold sheet-displacement-threshold - :expandHeaderLimit expand-header-limit}) + {:scroll-amount scroll-amount + :header-height header-height + :expand-header-threshold expand-header-threshold + :sheet-displacement-threshold sheet-displacement-threshold + :expand-header-limit expand-header-limit}) flat-list-ref (reanimated/use-animated-ref) _scroll-to-animation (worklets/use-scroll-to - #js {:animatedRef flat-list-ref - :scrollAmount scroll-amount - :expandHeaderLimit expand-header-limit}) + {:animated-ref flat-list-ref + :scroll-amount scroll-amount + :expand-header-limit expand-header-limit}) {:keys [joined? spectated?]} (rf/sub [:communities/community-overview community-id]) joined-or-spectated? (or joined? spectated?) @@ -290,14 +290,14 @@ (defn- header [community-id scroll-amount] (let [header-opacity (worklets/use-header-opacity - #js {:scrollAmount scroll-amount - :expandHeaderThreshold expand-header-threshold - :sheetDisplacementThreshold sheet-displacement-threshold}) + {:scroll-amount scroll-amount + :expand-header-threshold expand-header-threshold + :sheet-displacement-threshold sheet-displacement-threshold}) opposite-header-opacity (worklets/use-opposite-header-opacity header-opacity) nav-content-opacity (worklets/use-nav-content-opacity - #js {:scrollAmount scroll-amount - :sheetDisplacementThreshold sheet-displacement-threshold - :expandHeaderLimit expand-header-limit}) + {:scroll-amount scroll-amount + :sheet-displacement-threshold sheet-displacement-threshold + :expand-header-limit expand-header-limit}) {:keys [community-name color logo cover-image]} (rf/sub [:communities/community-overview community-id])] [:<> @@ -321,10 +321,10 @@ [{:keys [scroll-amount community-id]}] (let [theme (quo.theme/use-theme) logo-styles (worklets/use-logo-styles - #js {:scrollAmount scroll-amount - :expandHeaderThreshold expand-header-threshold - :sheetDisplacementThreshold sheet-displacement-threshold - :textMovementThreshold text-movement-threshold}) + {:scroll-amount scroll-amount + :expand-header-threshold expand-header-threshold + :sheet-displacement-threshold sheet-displacement-threshold + :text-movement-threshold text-movement-threshold}) {:keys [logo]} (rf/sub [:communities/community-overview community-id])] [reanimated/view {:style [style/community-logo @@ -335,9 +335,9 @@ (defn- name-and-description [{:keys [scroll-amount community-name community-description info-styles]}] (let [name-styles (worklets/use-name-styles - #js {:scrollAmount scroll-amount - :expandHeaderThreshold expand-header-threshold - :textMovementThreshold text-movement-threshold})] + {:scroll-amount scroll-amount + :expand-header-threshold expand-header-threshold + :text-movement-threshold text-movement-threshold})] [rn/view {:style style/community-name-and-description} [reanimated/view {:style name-styles} [quo/text {:weight :semi-bold :size :heading-1 :number-of-lines 1} @@ -372,12 +372,12 @@ [{:keys [scroll-amount header-height community-id]}] (let [theme (quo.theme/use-theme) sheet-styles (worklets/use-sheet-styles - #js {:scrollAmount scroll-amount - :expandHeaderThreshold expand-header-threshold - :sheetDisplacementThreshold sheet-displacement-threshold}) + {:scroll-amount scroll-amount + :expand-header-threshold expand-header-threshold + :sheet-displacement-threshold sheet-displacement-threshold}) info-styles (worklets/use-info-styles - #js {:scrollAmount scroll-amount - :infoOpacityThreshold info-opacity-threshold}) + {:scroll-amount scroll-amount + :info-opacity-threshold info-opacity-threshold}) set-header-height (rn/use-callback (fn [e] (let [height (oops/oget e "nativeEvent.layout.height")] @@ -438,17 +438,17 @@ scroll-amount (reanimated/use-shared-value (if expanded? 0 expand-header-threshold)) on-pan-start (worklets/on-pan-start scroll-start scroll-amount) on-pan-update (worklets/on-pan-update - #js {:scrollStart scroll-start - :scrollAmount scroll-amount - :maxScroll max-scroll - :expandHeaderLimit expand-header-limit}) + {:scroll-start scroll-start + :scroll-amount scroll-amount + :max-scroll max-scroll + :expand-header-limit expand-header-limit}) on-pan-end (worklets/on-pan-end - #js {:scrollStart scroll-start - :scrollAmount scroll-amount - :maxScroll max-scroll - :expandHeaderLimit expand-header-limit - :expandHeaderThreshold expand-header-threshold - :snapHeaderThreshold snap-header-threshold}) + {:scroll-start scroll-start + :scroll-amount scroll-amount + :max-scroll max-scroll + :expand-header-limit expand-header-limit + :expand-header-threshold expand-header-threshold + :snap-header-threshold snap-header-threshold}) pan-gesture (-> (gesture/gesture-pan) (gesture/on-start on-pan-start) (gesture/on-update on-pan-update) diff --git a/src/utils/transforms.cljs b/src/utils/transforms.cljs index 1c9c5c437d4..32885f7e09a 100644 --- a/src/utils/transforms.cljs +++ b/src/utils/transforms.cljs @@ -59,6 +59,7 @@ (def ->kebab-case-keyword (memoize csk/->kebab-case-keyword)) (def ->PascalCaseKeyword (memoize csk/->PascalCaseKeyword)) +(def ->camelCaseString (memoize csk/->camelCaseString)) (defn json->js [json] diff --git a/src/utils/worklets/communities.cljs b/src/utils/worklets/communities.cljs index 7b3b084e6d6..ef6d60217ce 100644 --- a/src/utils/worklets/communities.cljs +++ b/src/utils/worklets/communities.cljs @@ -1,17 +1,31 @@ -(ns utils.worklets.communities) +(ns utils.worklets.communities + (:require [goog.object :as gobj] + [react-native.utils :as utils] + [taoensso.timbre :as log])) (def worklets (js/require "../src/js/worklets/communities.js")) -(def use-logo-styles (.-useLogoStyles worklets)) -(def use-sheet-styles (.-useSheetStyles worklets)) -(def use-name-styles (.-useNameStyles worklets)) -(def use-info-styles (.-useInfoStyles worklets)) -(def use-channels-styles (.-useChannelsStyles worklets)) -(def use-scroll-to (.-useScrollTo worklets)) -(def use-header-opacity (.-useHeaderOpacity worklets)) -(def use-opposite-header-opacity (.-useOppositeHeaderOpacity worklets)) -(def use-nav-content-opacity (.-useNavContentOpacity worklets)) +(defn- transform-args [f] + (fn [& args] + (apply f (map utils/kebab-case-map->camelCase-obj args)))) -(def on-pan-start (.-onPanStart worklets)) -(def on-pan-update (.-onPanUpdate worklets)) -(def on-pan-end (.-onPanEnd worklets)) +(defn- worklet-wrapper [worklet-name] + (if-let [worklet-fn (gobj/get worklets worklet-name)] + (transform-args worklet-fn) + (log/error "Non-existing worklet!" + {:name worklet-name + :file "../src/js/worklets/communities.js"}))) + +(def use-logo-styles (worklet-wrapper "useLogoStyles")) +(def use-sheet-styles (worklet-wrapper "useSheetStyles")) +(def use-name-styles (worklet-wrapper "useNameStyles")) +(def use-info-styles (worklet-wrapper "useInfoStyles")) +(def use-channels-styles (worklet-wrapper "useChannelsStyles")) +(def use-scroll-to (worklet-wrapper "useScrollTo")) +(def use-header-opacity (worklet-wrapper "useHeaderOpacity")) +(def use-opposite-header-opacity (worklet-wrapper "useOppositeHeaderOpacity")) +(def use-nav-content-opacity (worklet-wrapper "useNavContentOpacity")) + +(def on-pan-start (worklet-wrapper "onPanStart")) +(def on-pan-update (worklet-wrapper "onPanUpdate")) +(def on-pan-end (worklet-wrapper "onPanEnd")) From 79dc6ddda055ae4732211604b2f6fa5024c40e73 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 18 Mar 2025 17:03:44 -0600 Subject: [PATCH 07/16] lint fix --- src/react_native/utils.cljs | 2 +- .../contexts/communities/overview/view.cljs | 28 +++++++++++-------- src/status_im/subs/communities.cljs | 2 +- src/utils/worklets/communities.cljs | 6 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/react_native/utils.cljs b/src/react_native/utils.cljs index c68ade61e08..16fcd758ada 100644 --- a/src/react_native/utils.cljs +++ b/src/react_native/utils.cljs @@ -48,6 +48,6 @@ (reduce-kv (fn [o k v] (doto o (gobj/set (transforms/->camelCaseString k) v))) - #js{} + #js {} m) m)) diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index e278ff8477a..1ce9b7da4ab 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -188,16 +188,20 @@ :channel 48 :separator 8}) -(defn- unusable-area-height [] +(defn- unusable-area-height + [] (+ (safe-area/get-top) - 32 11 ;;top page buttons & button's padding + 32 + 11 ;;top page buttons & button's padding (safe-area/get-bottom))) -(defn- calc-scrollable-content [scrollable-height] +(defn- calc-scrollable-content + [scrollable-height] (- (+ scrollable-height (unusable-area-height)) (:height (rn/get-window)))) -(defn- calc-listing-height [] +(defn- calc-listing-height + [] (- (:height (rn/get-window)) (unusable-area-height))) (defn- channel-listing @@ -299,7 +303,7 @@ :sheet-displacement-threshold sheet-displacement-threshold :expand-header-limit expand-header-limit}) {:keys [community-name color logo - cover-image]} (rf/sub [:communities/community-overview community-id])] + cover-image]} (rf/sub [:communities/community-overview community-id])] [:<> [header-cover-image {:cover-image cover-image @@ -319,12 +323,12 @@ (defn- community-logo [{:keys [scroll-amount community-id]}] - (let [theme (quo.theme/use-theme) - logo-styles (worklets/use-logo-styles - {:scroll-amount scroll-amount - :expand-header-threshold expand-header-threshold - :sheet-displacement-threshold sheet-displacement-threshold - :text-movement-threshold text-movement-threshold}) + (let [theme (quo.theme/use-theme) + logo-styles (worklets/use-logo-styles + {:scroll-amount scroll-amount + :expand-header-threshold expand-header-threshold + :sheet-displacement-threshold sheet-displacement-threshold + :text-movement-threshold text-movement-threshold}) {:keys [logo]} (rf/sub [:communities/community-overview community-id])] [reanimated/view {:style [style/community-logo @@ -476,7 +480,7 @@ :type :title :text-align :left :icon-name :i/close - :on-press #(rf/dispatch [:navigate-back])}] + :on-press events.helper/navigate-back}] [quo/empty-state {:image (resources/get-themed-image :cat-in-box theme) :description (when-not fetching? (i18n/label :t/here-is-a-cat-in-a-box-instead)) diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index ce0144c013d..8ad75153d0d 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -396,7 +396,7 @@ (if collapsed? (get-category-item category) (category-with-channels category-id category)))) - categorized-channels))) + categorized-channels))) (re-frame/reg-sub :communities/community-overview diff --git a/src/utils/worklets/communities.cljs b/src/utils/worklets/communities.cljs index ef6d60217ce..b2a5c975cf7 100644 --- a/src/utils/worklets/communities.cljs +++ b/src/utils/worklets/communities.cljs @@ -5,11 +5,13 @@ (def worklets (js/require "../src/js/worklets/communities.js")) -(defn- transform-args [f] +(defn- transform-args + [f] (fn [& args] (apply f (map utils/kebab-case-map->camelCase-obj args)))) -(defn- worklet-wrapper [worklet-name] +(defn- worklet-wrapper + [worklet-name] (if-let [worklet-fn (gobj/get worklets worklet-name)] (transform-args worklet-fn) (log/error "Non-existing worklet!" From 3df61e4e3469746f5041bc8c85c5d7c9eb15feca Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 18 Mar 2025 18:50:39 -0600 Subject: [PATCH 08/16] Add tests for sub :communities/flatten-channels-and-categories --- src/status_im/subs/communities_test.cljs | 181 ++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/src/status_im/subs/communities_test.cljs b/src/status_im/subs/communities_test.cljs index 8e3a5e8cc95..6acb183e1a6 100644 --- a/src/status_im/subs/communities_test.cljs +++ b/src/status_im/subs/communities_test.cljs @@ -349,7 +349,7 @@ [sub-name] (testing "returns a map keyed by the images of tokens/collectibles - And has data-uri as it's values" + And has data-uri as it's values" (swap! rf-db/app-db assoc-in [:communities community-id :tokens-metadata] [{:contract-addresses {:420 "0x1"} @@ -573,3 +573,182 @@ (is (= [member-1-id member-2-id] (rf/sub [sub-name community-id chat-id :offline])))))) + +(h/deftest-sub :communities/flatten-channels-and-categories + [sub-name] + (let [none-category {:name "None" :collapsed? nil :render-as :nothing} + separator {:render-as :separator} + chat (fn [{:keys [id chat-name position]}] + {:emoji nil + :muted? nil + :color nil + :name chat-name + :mentions-count 0 + :unread-messages? false + :hide-if-permissions-not-met? nil + :render-as :channel + :id id + :locked? false + :position position + :can-post? true}) + category (fn [{:keys [id category-name position collapsed?]}] + {:id id + :position position + :name category-name + :collapsed? collapsed? + :render-as :category})] + (testing "A list with the categories and channels" + (swap! rf-db/app-db assoc + :communities + {"0x1" {:id "0x1" + :chats {"0x1" {:id "0x1" + :position 1 + :name "chat1" + :muted? nil + :categoryID "1" + :token-gated? true + :can-post? true} + "0x2" {:id "0x2" + :position 2 + :name "chat2" + :muted? nil + :categoryID "1" + :token-gated? true + :can-post? true} + "0x3" {:id "0x3" + :position 3 + :name "chat3" + :muted? nil + :categoryID "2" + :token-gated? true + :can-post? true} + "0x4" {:id "0x4" + :position 4 + :name "chat4" + :muted? nil + :categoryID "" + :token-gated? true + :can-post? true}} + :categories {"1" {:id "1" + :position 2 + :name "category1"} + "2" {:id "2" + :position 1 + :name "category2"}} + :joined true}}) + (is + (= [none-category + (chat {:id "0x4" + :chat-name "chat4" + :position 4}) + separator + (category {:id "2" + :category-name "category2" + :position 1}) + (chat {:id "0x3" + :chat-name "chat3" + :position 3}) + separator + (category {:id "1" + :category-name "category1" + :position 2}) + (chat {:id "0x1" + :chat-name "chat1" + :position 1}) + (chat {:id "0x2" + :chat-name "chat2" + :position 2}) + separator] + (rf/sub [sub-name "0x1"])))) + + (testing "All chats are uncategorized" + (swap! rf-db/app-db assoc + :communities + {"0x1" {:id "0x1" + :chats {"0x1" {:id "0x1" + :position 1 + :name "chat1" + :muted? nil + :categoryID "" + :token-gated? true + :can-post? true} + "0x2" {:id "0x2" + :position 2 + :name "chat2" + :muted? nil + :categoryID "" + :token-gated? true + :can-post? true} + "0x3" {:id "0x3" + :position 3 + :name "chat3" + :muted? nil + :categoryID "" + :token-gated? true + :can-post? true}} + :joined true}}) + (is (= [none-category + (chat {:id "0x1" + :chat-name "chat1" + :position 1}) + (chat {:id "0x2" + :chat-name "chat2" + :position 2}) + (chat {:id "0x3" + :chat-name "chat3" + :position 3}) + separator] + (rf/sub [sub-name "0x1"])))) + + (testing "Collapsed categories don't include their channels" + (swap! rf-db/app-db assoc + :communities/collapsed-categories {"0x1" {"1" true "2" true}} + :communities + {"0x1" {:id "0x1" + :chats {"0x1" {:id "0x1" + :position 1 + :name "chat1" + :muted? nil + :categoryID "1" + :token-gated? false + :can-post? true} + "0x2" {:id "0x2" + :position 2 + :name "chat2" + :muted? nil + :categoryID "2" + :token-gated? true + :can-post? false} + "0x3" {:id "0x3" + :position 3 + :name "chat3" + :muted? nil + :categoryID "3" + :token-gated? true + :can-post? true}} + :categories {"1" {:id "1" + :position 1 + :name "category1"} + "2" {:id "2" + :position 2 + :name "category2"} + "3" {:id "3" + :position 3 + :name "category3"}} + :joined true}}) + (is (= [(category {:id "1" + :category-name "category1" + :position 1 + :collapsed? true}) + (category {:id "2" + :category-name "category2" + :position 2 + :collapsed? true}) + (category {:id "3" + :category-name "category3" + :position 3}) + (chat {:id "0x3" + :chat-name "chat3" + :position 3}) + separator] + (rf/sub [sub-name "0x1"])))))) From d99e25a990ad5ccc5f2e1671c92d63c98c0c6d03 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 20 Mar 2025 16:09:57 -0600 Subject: [PATCH 09/16] Throw an exception for non-existing worklets --- src/status_im/subs/communities.cljs | 4 ++-- src/utils/worklets/communities.cljs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index 8ad75153d0d..2eabd3f3e21 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -330,8 +330,8 @@ :position position :mentions-count (or unviewed-mentions-count 0) :can-post? can-post? - ;; NOTE: this is a troolean nil->no permissions, true->no access, false - ;; -> has access + ;; NOTE: this is a troolean nil->no permissions, true->no access, + ;; false -> has access :locked? locked? :hide-if-permissions-not-met? (and hide-if-permissions-not-met? locked?) :id id diff --git a/src/utils/worklets/communities.cljs b/src/utils/worklets/communities.cljs index b2a5c975cf7..5476f8c3269 100644 --- a/src/utils/worklets/communities.cljs +++ b/src/utils/worklets/communities.cljs @@ -1,9 +1,8 @@ (ns utils.worklets.communities (:require [goog.object :as gobj] - [react-native.utils :as utils] - [taoensso.timbre :as log])) + [react-native.utils :as utils])) -(def worklets (js/require "../src/js/worklets/communities.js")) +(def ^:private worklets (js/require "../src/js/worklets/communities.js")) (defn- transform-args [f] @@ -14,9 +13,10 @@ [worklet-name] (if-let [worklet-fn (gobj/get worklets worklet-name)] (transform-args worklet-fn) - (log/error "Non-existing worklet!" - {:name worklet-name - :file "../src/js/worklets/communities.js"}))) + (throw (js/Error. + (ex-info "Non-existing worklet!" + {:name worklet-name + :file "../src/js/worklets/communities.js"}))))) (def use-logo-styles (worklet-wrapper "useLogoStyles")) (def use-sheet-styles (worklet-wrapper "useSheetStyles")) From 93b5da5b9c7e94d86b78d4c8e6614a682c050546 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 20 Mar 2025 16:41:53 -0600 Subject: [PATCH 10/16] Abstract some values --- src/js/worklets/communities.js | 20 +++++++++++-------- .../contexts/communities/overview/view.cljs | 19 +++++++++--------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/js/worklets/communities.js b/src/js/worklets/communities.js index 0470cb640d5..30d66f36162 100644 --- a/src/js/worklets/communities.js +++ b/src/js/worklets/communities.js @@ -187,13 +187,15 @@ export function onScrollAnimationEnd( expandHeaderThreshold, snapHeaderThreshold, expandHeaderLimit, + animationDuration, ) { 'worklet'; return function () { + const duration = {duration: animationDuration} 'worklet'; if (scrollAmount.value > snapHeaderThreshold && scrollAmount.value <= expandHeaderThreshold) { - scrollStart.value = withTiming(-expandHeaderThreshold, { duration: 300 }); - scrollAmount.value = withTiming(expandHeaderThreshold, { duration: 300 }); + scrollStart.value = withTiming(-expandHeaderThreshold, duration); + scrollAmount.value = withTiming(expandHeaderThreshold, duration); } if (scrollAmount.value > expandHeaderThreshold) { @@ -201,17 +203,17 @@ export function onScrollAnimationEnd( } if (scrollAmount.value <= snapHeaderThreshold) { - scrollStart.value = withTiming(0, { duration: 300 }); - scrollAmount.value = withTiming(0, { duration: 300 }); + scrollStart.value = withTiming(0, duration); + scrollAmount.value = withTiming(0, duration); } if (scrollAmount.value > expandHeaderThreshold && scrollAmount.value < expandHeaderLimit) { if (scrollAmount.value >= (expandHeaderLimit - expandHeaderThreshold) * 0.65 + expandHeaderThreshold) { - scrollAmount.value = withTiming(expandHeaderLimit, { duration: 300 }); - scrollStart.value = withTiming(-expandHeaderLimit, { duration: 300 }); + scrollAmount.value = withTiming(expandHeaderLimit, duration); + scrollStart.value = withTiming(-expandHeaderLimit, duration); } else { - scrollAmount.value = withTiming(expandHeaderThreshold, { duration: 300 }); - scrollStart.value = withTiming(-expandHeaderThreshold, { duration: 300 }); + scrollAmount.value = withTiming(expandHeaderThreshold, duration); + scrollStart.value = withTiming(-expandHeaderThreshold, duration); } } }; @@ -246,6 +248,7 @@ export function onPanEnd({ expandHeaderLimit, expandHeaderThreshold, snapHeaderThreshold, + animationDuration, }) { const isIOS = Platform.OS === 'ios'; return function (event) { @@ -257,6 +260,7 @@ export function onPanEnd({ expandHeaderThreshold, snapHeaderThreshold, expandHeaderLimit, + animationDuration, ); if (scrollAmount.value < expandHeaderLimit) { endAnimation(); diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 1ce9b7da4ab..bd1f14c7494 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -21,7 +21,7 @@ [utils.worklets.communities :as worklets])) ;; NOTE: values compared against `scroll-amount` to trigger animations. -(def expand-header-threshold 150) +(def expand-header-threshold 150) ;; drag distance to collapse/extend the community (def sheet-displacement-threshold (+ expand-header-threshold 20)) (def text-movement-threshold (* expand-header-threshold 0.7)) (def info-opacity-threshold (* expand-header-threshold 0.5)) @@ -433,13 +433,13 @@ :set-max-scroll set-max-scroll}]])) (defn- community-overview - [community-id expanded?] + [community-id collapsed?] (let [max-scroll (reanimated/use-shared-value 0) set-max-scroll (rn/use-callback (fn [max-scroll-amount] (reanimated/set-shared-value max-scroll max-scroll-amount))) - scroll-start (reanimated/use-shared-value (if expanded? 0 (- expand-header-threshold))) - scroll-amount (reanimated/use-shared-value (if expanded? 0 expand-header-threshold)) + scroll-start (reanimated/use-shared-value (if collapsed? (- expand-header-threshold) 0)) + scroll-amount (reanimated/use-shared-value (if collapsed? expand-header-threshold 0)) on-pan-start (worklets/on-pan-start scroll-start scroll-amount) on-pan-update (worklets/on-pan-update {:scroll-start scroll-start @@ -452,7 +452,8 @@ :max-scroll max-scroll :expand-header-limit expand-header-limit :expand-header-threshold expand-header-threshold - :snap-header-threshold snap-header-threshold}) + :snap-header-threshold snap-header-threshold + :animation-duration 300}) pan-gesture (-> (gesture/gesture-pan) (gesture/on-start on-pan-start) (gesture/on-update on-pan-update) @@ -491,10 +492,10 @@ (defn view [id] - (let [community-id (or id (rf/sub [:get-screen-params :community-overview])) - community (rf/sub [:communities/community-overview community-id]) - start-expanded? (:joined? community)] + (let [community-id (or id (rf/sub [:get-screen-params :community-overview])) + community (rf/sub [:communities/community-overview community-id]) + collapsed? (:joined? community)] [rn/view {:style style/community-overview-container} (if community - [community-overview community-id start-expanded?] + [community-overview community-id collapsed?] [community-fetching-placeholder community-id])])) From aaa72c6ca1f4dba549b7208cbdbe5c6053efa946 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Thu, 20 Mar 2025 16:50:10 -0600 Subject: [PATCH 11/16] Add docstrings to animation vars --- src/js/worklets/communities.js | 2 +- .../contexts/communities/overview/view.cljs | 31 +++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/js/worklets/communities.js b/src/js/worklets/communities.js index 30d66f36162..8ac586a09b9 100644 --- a/src/js/worklets/communities.js +++ b/src/js/worklets/communities.js @@ -191,8 +191,8 @@ export function onScrollAnimationEnd( ) { 'worklet'; return function () { - const duration = {duration: animationDuration} 'worklet'; + const duration = { duration: animationDuration }; if (scrollAmount.value > snapHeaderThreshold && scrollAmount.value <= expandHeaderThreshold) { scrollStart.value = withTiming(-expandHeaderThreshold, duration); scrollAmount.value = withTiming(expandHeaderThreshold, duration); diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index bd1f14c7494..41e6e41c700 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -21,12 +21,31 @@ [utils.worklets.communities :as worklets])) ;; NOTE: values compared against `scroll-amount` to trigger animations. -(def expand-header-threshold 150) ;; drag distance to collapse/extend the community -(def sheet-displacement-threshold (+ expand-header-threshold 20)) -(def text-movement-threshold (* expand-header-threshold 0.7)) -(def info-opacity-threshold (* expand-header-threshold 0.5)) -(def expand-header-limit (+ sheet-displacement-threshold 56)) -(def snap-header-threshold (* expand-header-threshold 0.75)) +(def expand-header-threshold + "Dragging distance to collapse/extend the community." + 150) + +(def sheet-displacement-threshold + "Dragging distance to round sheet borders and move the sheet 8 units." + (+ expand-header-threshold 20)) + +(def text-movement-threshold + "Dragging distance to start the text movement from/to the bottom to/from the right." + (* expand-header-threshold 0.7)) + +(def info-opacity-threshold + "Dragging distance to appear/disappear the community info (description, tags & stats)." + (* expand-header-threshold 0.5)) + +(def snap-header-threshold + "Threshold to automatically move the header to a collapsed/expanded state and avoid an + intermediate state." + (* expand-header-threshold 0.75)) + +(def expand-header-limit + "Max dragging distance where the header animation ends. It works to identify when to + start the flat-list scrolling." + (+ sheet-displacement-threshold 56)) (defn- collapse-category [community-id category-id collapsed?] From 1156ffff69bc9bd1d769b94a09bc6f80b28bb04e Mon Sep 17 00:00:00 2001 From: Ulises M Date: Fri, 21 Mar 2025 07:45:38 -0600 Subject: [PATCH 12/16] Add worklets to test --- src/mocks/js_dependencies.cljs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index 0e0c26e4d0c..8ea621f1eba 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -429,7 +429,18 @@ (slurp "./resources/data/emojis/en.json")) "../src/js/worklets/core.js" worklet-factory - "../src/js/worklets/communities.js" #js {} + "../src/js/worklets/communities.js" #js {"useLogoStyles" #js {} + "useSheetStyles" #js {} + "useNameStyles" #js {} + "useInfoStyles" #js {} + "useChannelsStyles" #js {} + "useScrollTo" #js {} + "useHeaderOpacity" #js {} + "useOppositeHeaderOpacity" #js {} + "useNavContentOpacity" #js {} + "onPanStart" #js {} + "onPanUpdate" #js {} + "onPanEnd" #js {}} "../src/js/worklets/shell/bottom_tabs.js" #js {} "../src/js/worklets/shell/home_stack.js" #js {} "../src/js/worklets/bottom_sheet.js" #js {} From a23cea3931b0f3f30b6650fe34fd24fcf9cd69bb Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 25 Mar 2025 14:13:46 -0600 Subject: [PATCH 13/16] Return accs labels --- src/status_im/contexts/communities/overview/view.cljs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 41e6e41c700..248ec12dc29 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -363,10 +363,15 @@ :text-movement-threshold text-movement-threshold})] [rn/view {:style style/community-name-and-description} [reanimated/view {:style name-styles} - [quo/text {:weight :semi-bold :size :heading-1 :number-of-lines 1} + [quo/text {:accessibility-label :community-title + :weight :semi-bold + :size :heading-1 + :number-of-lines 2} community-name]] [reanimated/view {:style [{:opacity 0} info-styles]} - [quo/text {:weight :regular :size :paragraph-1} + [quo/text {:accessibility-label :community-description + :weight :regular + :size :paragraph-1} community-description]]])) (defn- community-info-tags From de229580c7602dfa29e729898ff6c0b844dab034 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 25 Mar 2025 14:43:25 -0600 Subject: [PATCH 14/16] Fix community name not fitting into the compressed version --- src/js/worklets/communities.js | 6 +++--- src/status_im/contexts/communities/overview/view.cljs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/js/worklets/communities.js b/src/js/worklets/communities.js index 8ac586a09b9..b16a0497fdb 100644 --- a/src/js/worklets/communities.js +++ b/src/js/worklets/communities.js @@ -81,11 +81,11 @@ export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDispl export function useNameStyles({ scrollAmount, expandHeaderThreshold, textMovementThreshold }) { return useAnimatedStyle(() => { + const animationProgress = interpolate(scrollAmount.value, [textMovementThreshold, expandHeaderThreshold], [0, 40], 'clamp'); return { + marginRight: animationProgress, transform: [ - { - translateX: interpolate(scrollAmount.value, [textMovementThreshold, expandHeaderThreshold], [0, 40], 'clamp'), - }, + {translateX: animationProgress}, { translateY: interpolate( scrollAmount.value, diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 248ec12dc29..70a236e3f58 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -366,7 +366,7 @@ [quo/text {:accessibility-label :community-title :weight :semi-bold :size :heading-1 - :number-of-lines 2} + :number-of-lines 1} community-name]] [reanimated/view {:style [{:opacity 0} info-styles]} [quo/text {:accessibility-label :community-description From e3f0f26ad7b7f7cf0a0304cd72deebfcc75e40ef Mon Sep 17 00:00:00 2001 From: Ulises M Date: Tue, 25 Mar 2025 14:48:03 -0600 Subject: [PATCH 15/16] Lint fix --- src/js/worklets/communities.js | 9 +++++++-- .../components/navigation/page_nav/style.cljs | 3 ++- .../contexts/communities/overview/view.cljs | 16 +++++++++------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/js/worklets/communities.js b/src/js/worklets/communities.js index b16a0497fdb..4d328def86b 100644 --- a/src/js/worklets/communities.js +++ b/src/js/worklets/communities.js @@ -81,11 +81,16 @@ export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDispl export function useNameStyles({ scrollAmount, expandHeaderThreshold, textMovementThreshold }) { return useAnimatedStyle(() => { - const animationProgress = interpolate(scrollAmount.value, [textMovementThreshold, expandHeaderThreshold], [0, 40], 'clamp'); + const animationProgress = interpolate( + scrollAmount.value, + [textMovementThreshold, expandHeaderThreshold], + [0, 40], + 'clamp', + ); return { marginRight: animationProgress, transform: [ - {translateX: animationProgress}, + { translateX: animationProgress }, { translateY: interpolate( scrollAmount.value, diff --git a/src/quo/components/navigation/page_nav/style.cljs b/src/quo/components/navigation/page_nav/style.cljs index 9475a81926d..c085ef97b22 100644 --- a/src/quo/components/navigation/page_nav/style.cljs +++ b/src/quo/components/navigation/page_nav/style.cljs @@ -34,7 +34,8 @@ (defn right-content [min-size? centered-content?] (cond-> {} - centered-content? (assoc :flex-grow 1 :flex-basis 1) + centered-content? (assoc :flex-grow 1 + :flex-basis 1) min-size? (assoc :min-height 32))) (def token-logo diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 70a236e3f58..a1297079827 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -363,15 +363,17 @@ :text-movement-threshold text-movement-threshold})] [rn/view {:style style/community-name-and-description} [reanimated/view {:style name-styles} - [quo/text {:accessibility-label :community-title - :weight :semi-bold - :size :heading-1 - :number-of-lines 1} + [quo/text + {:accessibility-label :community-title + :weight :semi-bold + :size :heading-1 + :number-of-lines 1} community-name]] [reanimated/view {:style [{:opacity 0} info-styles]} - [quo/text {:accessibility-label :community-description - :weight :regular - :size :paragraph-1} + [quo/text + {:accessibility-label :community-description + :weight :regular + :size :paragraph-1} community-description]]])) (defn- community-info-tags From 7d02adb66a5b031d54bd33e6974b3a626ff302a8 Mon Sep 17 00:00:00 2001 From: Ulises M Date: Wed, 26 Mar 2025 14:28:12 -0600 Subject: [PATCH 16/16] fix to quo.context --- .../contexts/communities/overview/view.cljs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index a1297079827..7af91f39d0e 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -1,8 +1,8 @@ (ns status-im.contexts.communities.overview.view (:require [oops.core :as oops] + [quo.context] [quo.core :as quo] - [quo.theme] [react-native.core :as rn] [react-native.gesture :as gesture] [react-native.platform :as platform] @@ -131,7 +131,7 @@ {collapsed? :collapsed? category-name :name category-id :id}] - (let [theme (quo.theme/use-theme)] + (let [theme (quo.context/use-theme)] [rn/view {:style (style/category-divider theme) :blur-amount 20 @@ -225,7 +225,7 @@ (defn- channel-listing [{:keys [community-id scroll-amount header-height set-max-scroll]}] - (let [theme (quo.theme/use-theme) + (let [theme (quo.context/use-theme) channels-styles (worklets/use-channels-styles {:scroll-amount scroll-amount :header-height header-height @@ -271,7 +271,7 @@ (defn- header-cover-image [{:keys [cover-image background-color header-opacity]}] - (let [theme (quo.theme/use-theme)] + (let [theme (quo.context/use-theme)] [rn/view {:style (style/header-cover-image background-color)} [reanimated/image {:style style/cover-image :source {:uri cover-image}}] [reanimated/view {:style (style/cover-image-blur-container header-opacity)} @@ -342,7 +342,7 @@ (defn- community-logo [{:keys [scroll-amount community-id]}] - (let [theme (quo.theme/use-theme) + (let [theme (quo.context/use-theme) logo-styles (worklets/use-logo-styles {:scroll-amount scroll-amount :expand-header-threshold expand-header-threshold @@ -400,7 +400,7 @@ (defn- community-info [{:keys [scroll-amount header-height community-id]}] - (let [theme (quo.theme/use-theme) + (let [theme (quo.context/use-theme) sheet-styles (worklets/use-sheet-styles {:scroll-amount scroll-amount :expand-header-threshold expand-header-threshold @@ -494,7 +494,7 @@ (defn- community-fetching-placeholder [id] - (let [theme (quo.theme/use-theme) + (let [theme (quo.context/use-theme) top-inset (safe-area/get-top) fetching? (rf/sub [:communities/fetching-community id])] [rn/view