diff --git a/src/quo2/components/avatars/channel_avatar.cljs b/src/quo2/components/avatars/channel_avatar.cljs index 01d9395d14..76a58c60aa 100644 --- a/src/quo2/components/avatars/channel_avatar.cljs +++ b/src/quo2/components/avatars/channel_avatar.cljs @@ -7,7 +7,7 @@ (defn channel-avatar [{:keys [big? locked? emoji-background-color emoji]}] - (let [lock-exists? (some? locked?) + (let [lock-exists? locked? dark? (theme/dark?)] [rn/view {:style {:width (if big? 32 24) diff --git a/src/status_im2/common/scroll_page/view.cljs b/src/status_im2/common/scroll_page/view.cljs index c2e6ffcd9e..aef4373b02 100644 --- a/src/status_im2/common/scroll_page/view.cljs +++ b/src/status_im2/common/scroll_page/view.cljs @@ -28,98 +28,100 @@ (defn scroll-page-header [scroll-height name page-nav cover sticky-header] - [:f> - (fn [] - (let [input-range (if platform/ios? [-47 10] [0 150]) - output-range (if platform/ios? [-100 0] [-169 -45]) - y (reanimated/use-shared-value @scroll-height) - translate-animation (reanimated/interpolate y - input-range - output-range - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"}) - opacity-animation (reanimated/use-shared-value 0) - threshold (if platform/ios? 30 170)] - (rn/use-effect - #(do - (reanimated/set-shared-value y @scroll-height) - (reanimated/set-shared-value opacity-animation - (reanimated/with-timing (if (>= @scroll-height threshold) 1 0) - (clj->js {:duration 300})))) - [@scroll-height]) - [:<> - [reanimated/blur-view - {:blur-amount 32 - :blur-type :xlight - :overlay-color (if platform/ios? colors/white-opa-70 :transparent) - :style (style/blur-slider translate-animation)}] - [rn/view - {:style {:z-index 6 - :margin-top (if platform/ios? 44 0)}} - [reanimated/view - {:style (style/sticky-header-title opacity-animation)} - [rn/image - {:source cover - :style style/sticky-header-image}] - [quo/text - {:size :paragraph-1 - :weight :semi-bold - :style {:line-height 21}} - name]] - [quo/page-nav - {:horizontal-description? true - :one-icon-align-left? true - :align-mid? false - :page-nav-color :transparent - :mid-section {:type :text-with-description - :main-text nil - :description-img nil} - :right-section-buttons (:right-section-buttons page-nav) - :left-section {:icon :i/close - :icon-background-color (icon-color) - :on-press #(rf/dispatch [:navigate-back])}}] - (when sticky-header [sticky-header @scroll-height])]]))]) + (let [input-range (if platform/ios? [-47 10] [0 150]) + output-range (if platform/ios? [-100 0] [-169 -45]) + y (reanimated/use-shared-value scroll-height) + translate-animation (reanimated/interpolate y + input-range + output-range + {:extrapolateLeft "clamp" + :extrapolateRight "clamp"}) + opacity-animation (reanimated/use-shared-value 0) + threshold (if platform/ios? 30 170)] + (rn/use-effect + #(do + (reanimated/set-shared-value y scroll-height) + (reanimated/set-shared-value opacity-animation + (reanimated/with-timing (if (>= scroll-height threshold) 1 0) + (clj->js {:duration 300})))) + [scroll-height]) + [:<> + [reanimated/blur-view + {:blur-amount 32 + :blur-type :xlight + :overlay-color (if platform/ios? colors/white-opa-70 :transparent) + :style (style/blur-slider translate-animation)}] + [rn/view + {:style {:z-index 6 + :margin-top (if platform/ios? 44 0)}} + [reanimated/view + {:style (style/sticky-header-title opacity-animation)} + [rn/image + {:source cover + :style style/sticky-header-image}] + [quo/text + {:size :paragraph-1 + :weight :semi-bold + :style {:line-height 21}} + name]] + [quo/page-nav + {:horizontal-description? true + :one-icon-align-left? true + :align-mid? false + :page-nav-color :transparent + :mid-section {:type :text-with-description + :main-text nil + :description-img nil} + :right-section-buttons (:right-section-buttons page-nav) + :left-section {:icon :i/close + :icon-background-color (icon-color) + :on-press #(rf/dispatch [:navigate-back])}}] + sticky-header]])) + (defn display-picture [scroll-height cover] - [:f> - (fn [] - (let [input-range (if platform/ios? [-67 10] [0 150]) - y (reanimated/use-shared-value @scroll-height) - animation (reanimated/interpolate y - input-range - [1.2 0.5] - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"})] - (rn/use-effect #(do - (reanimated/set-shared-value y @scroll-height) - js/undefined) - [@scroll-height]) - [reanimated/view - {:style (style/display-picture-container animation)} - [rn/image - {:source cover - :style style/display-picture}]]))]) + (let [input-range (if platform/ios? [-67 10] [0 150]) + y (reanimated/use-shared-value scroll-height) + animation (reanimated/interpolate y + input-range + [1.2 0.5] + {:extrapolateLeft "clamp" + :extrapolateRight "clamp"})] + (rn/use-effect #(do + (reanimated/set-shared-value y scroll-height) + js/undefined) + [scroll-height]) + [reanimated/view + {:style (style/display-picture-container animation)} + [rn/image + {:source cover + :style style/display-picture}]])) (defn scroll-page - [cover page-nav name] + [_ _ _] (let [scroll-height (reagent/atom negative-scroll-position-0)] - (fn [sticky-header children] + (fn [{:keys [cover-image page-nav-right-section-buttons name on-scroll]} + sticky-header + children] [:<> - [scroll-page-header scroll-height name page-nav cover sticky-header] + [:f> scroll-page-header @scroll-height name page-nav-right-section-buttons cover-image + sticky-header] [rn/scroll-view {:style (style/scroll-view-container (diff-with-max-min @scroll-height 16 0)) :shows-vertical-scroll-indicator false :scroll-event-throttle 16 - :on-scroll (fn [event] + :on-scroll (fn [^js event] (reset! scroll-height (int (oops/oget event - "nativeEvent.contentOffset.y"))))} + "nativeEvent.contentOffset.y"))) + (when on-scroll + (on-scroll @scroll-height)))} [rn/view {:style {:height 151}} [rn/image - {:source cover + {:source cover-image :style {:overflow :visible :flex 1}}]] (when children @@ -129,5 +131,5 @@ :background-color (colors/theme-colors colors/white colors/neutral-90)} - [display-picture scroll-height cover] - [children]])]]))) + [:f> display-picture @scroll-height cover-image] + children])]]))) diff --git a/src/status_im2/contexts/chat/events.cljs b/src/status_im2/contexts/chat/events.cljs index 9dac4d9a0a..9dc645cd33 100644 --- a/src/status_im2/contexts/chat/events.cljs +++ b/src/status_im2/contexts/chat/events.cljs @@ -203,7 +203,7 @@ [{db :db :as cofx} chat-id from-shell?] (rf/merge cofx {:dispatch [:navigate-to-nav2 :chat chat-id from-shell?]} - (when-not (= (:view-id db) :community) + (when-not (or (= (:view-id db) :community) (= (:view-id db) :community-overview)) (navigation/pop-to-root-tab :shell-stack)) (close-chat false) (force-close-chat chat-id) diff --git a/src/status_im2/contexts/communities/home/view.cljs b/src/status_im2/contexts/communities/home/view.cljs index ef97c9a591..8b87f75a29 100644 --- a/src/status_im2/contexts/communities/home/view.cljs +++ b/src/status_im2/contexts/communities/home/view.cljs @@ -11,10 +11,7 @@ [id] (let [community-item (rf/sub [:communities/home-item id])] [quo/communities-membership-list-item - {:on-press (fn [] - (rf/dispatch [:communities/load-category-states id]) - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:navigate-to-nav2 :community {:community-id id}])) + {:on-press #(rf/dispatch [:navigate-to :community-overview id]) :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet {:content (fn [] diff --git a/src/status_im2/contexts/communities/overview/style.cljs b/src/status_im2/contexts/communities/overview/style.cljs index 6863eef87e..8273ab16df 100644 --- a/src/status_im2/contexts/communities/overview/style.cljs +++ b/src/status_im2/contexts/communities/overview/style.cljs @@ -20,16 +20,15 @@ :margin-left :auto :margin-right :auto}) -(defn scroll-view-container - [border-radius] - {:position :absolute - :top -48 - :overflow :scroll - :border-radius border-radius - :height "100%"}) - (def review-notice {:color colors/neutral-50 :margin-top 12 :margin-left :auto :margin-right :auto}) + +(def community-overview-container + {:position :absolute + :top (if platform/ios? 0 44) + :left 0 + :right 0 + :bottom 0}) diff --git a/src/status_im2/contexts/communities/overview/utils.cljs b/src/status_im2/contexts/communities/overview/utils.cljs new file mode 100644 index 0000000000..476435e7ab --- /dev/null +++ b/src/status_im2/contexts/communities/overview/utils.cljs @@ -0,0 +1,21 @@ +(ns status-im2.contexts.communities.overview.utils + (:require [clojure.string :as string] + [utils.i18n :as i18n])) + +(defn join-existing-users-string + [user-list] + (let [users-count (count user-list) + first-two (->> user-list + (take 2) + (map #(string/split (:full-name %) #" ")) + (map first))] + (case users-count + 0 "" + 1 (i18n/label :t/join-one-user {:user (first first-two)}) + 2 (i18n/label :join-two-users + {:user1 (first first-two) + :user2 (second first-two)}) + (i18n/label :join-more-users + {:user1 (first first-two) + :user2 (second first-two) + :left-count (- users-count 2)})))) diff --git a/src/status_im2/contexts/communities/overview/utils_test.cljs b/src/status_im2/contexts/communities/overview/utils_test.cljs new file mode 100644 index 0000000000..0d4c541115 --- /dev/null +++ b/src/status_im2/contexts/communities/overview/utils_test.cljs @@ -0,0 +1,29 @@ +(ns status-im2.contexts.communities.overview.utils-test + (:require [cljs.test :refer-macros [deftest is testing]] + [status-im2.contexts.communities.overview.utils :as u])) + +(deftest open-activity-center-test + (testing "One user" + (let [users [{:full-name "Alicia K"}]] + + (is (= "Join Alicia" + (u/join-existing-users-string users))))) + (testing "Two users" + (let [users [{:full-name "Alicia K"} + {:full-name "Marcus C"}]] + (is (= "Join Alicia and Marcus" + (u/join-existing-users-string users))))) + (testing "Three users" + (let [users [{:full-name "Alicia K"} + {:full-name "Marcus C"} + {:full-name "MNO PQR"}]] + (is (= "Join Alicia, Marcus and 1 more" + (u/join-existing-users-string users))))) + (testing "Four users" + (let [users [{:full-name "Alicia K"} + {:full-name "Marcus C"} + {:full-name "MNO PQR"} + {:full-name "STU VWX"}]] + + (is (= "Join Alicia, Marcus and 2 more" + (u/join-existing-users-string users)))))) diff --git a/src/status_im2/contexts/communities/overview/view.cljs b/src/status_im2/contexts/communities/overview/view.cljs index 3ba63c7197..c7a0466899 100644 --- a/src/status_im2/contexts/communities/overview/view.cljs +++ b/src/status_im2/contexts/communities/overview/view.cljs @@ -12,164 +12,94 @@ [status-im2.contexts.communities.overview.style :as style] [status-im2.contexts.communities.menus.community-options.view :as options] [status-im2.contexts.communities.menus.request-to-join.view :as join-menu] + [status-im2.contexts.communities.overview.utils :as utils] [utils.re-frame :as rf])) -(def knc-token-img (js/require "../resources/images/tokens/mainnet/KNC.png")) -(def mana-token-img (js/require "../resources/images/tokens/mainnet/MANA.png")) -(def rare-token-img (js/require "../resources/images/tokens/mainnet/RARE.png")) -(def eth-token-img (js/require "../resources/images/tokens/mainnet/ETH.png")) -(def dai-token-img (js/require "../resources/images/tokens/mainnet/DAI.png")) - -;; Mocked list items -(def user-list - [{:full-name "Alicia K"} - {:full-name "Marcus C"} - {:full-name "MNO PQR"} - {:full-name "STU VWX"}]) (defn preview-user-list - [] + [user-list] [rn/view style/preview-user [quo/preview-list {:type :user - :user user-list - :list-size 4 - :size 24}] + :list-size (count user-list) + :size 24} + user-list] [quo/text {:accessibility-label :communities-screen-title :style {:margin-left 8} :size :label} - "Join Alicia, Marcus and 2 more"]]) ;; TODO remove mocked data and use from contacts list/communities members + (utils/join-existing-users-string user-list)]]) -(defn open-token-gating-mocked - [name emoji channel-color] - #(rf/dispatch - [:bottom-sheet/show-sheet - {:content - (fn [] - [quo/token-gating - {:channel {:name name - :community-color (colors/custom-color :pink 50) - :emoji emoji - :emoji-background-color channel-color - :on-enter-channel (fn [] - (js/alert - "Entered channel" - "Wuhuu!! You successfully entered the channel :)")) - :gates {:read [{:token "KNC" - :token-img-src knc-token-img - :amount 200 - :is-sufficient? true} - {:token "MANA" - :token-img-src mana-token-img - :amount 10 - :is-sufficient? false - :is-purchasable true} - {:token "RARE" - :token-img-src rare-token-img - :amount 10 - :is-sufficient? false}] - :write [{:token "KNC" - :token-img-src knc-token-img - :amount 200 - :is-sufficient? true} - {:token "DAI" - :token-img-src dai-token-img - :amount 20 - :is-purchasable true - :is-sufficient? false} - {:token "ETH" - :token-img-src eth-token-img - :amount 0.5 - :is-sufficient? false}]}}}]) - :content-height 210}])) +(defn channel-token-gating-details + [name token-gating emoji channel-color] + [rn/view {:height 350 :margin-top 20} + [quo/token-gating + {:channel {:name name + :community-color channel-color + :emoji emoji + :emoji-background-color channel-color + :on-enter-channel (fn [] + (js/alert + "Entered channel" + "Wuhuu!! You successfully entered the channel :)")) + :gates token-gating}}]]) -(def mock-list-of-channels - {:Welcome [{:name "welcome" - :emoji "🤝"} - {:name "onboarding" - :emoji "🍑" - :locked? true - :on-press #((open-token-gating-mocked - "onboarding" - "🍑" - (colors/custom-color :pink 50)))} - {:name "intro" - :emoji "🦄" - :locked? true - :on-press #((open-token-gating-mocked - "intro" - "🦄" - (colors/custom-color :pink 50)))}] - :General [{:name "general" - :emoji "🐷"} - {:name "people-ops" - :emoji "🌏" - :locked? true - :on-press #((open-token-gating-mocked - "onboarding" - "🌏" - (colors/custom-color :blue 50)))} - {:name "announcements" - :emoji "🎺"}] - :Mobile [{:name "mobile" - :emoji "👽"} - {:name "mobile-ui" - :emoji "👽"} - {:name "mobile-ui-reviews" - :emoji "👽"}] - :Desktop [{:name "desktop" - :emoji "👽"} - {:name "desktop-ui" - :emoji "👽"} - {:name "desktop-ui-reviews" - :emoji "👽"} - {:name "desktop2" - :emoji "👽"} - {:name "desktop-ui2" - :emoji "👽"} - {:name "desktop-ui2-reviews" - :emoji "👽"}]}) +(defn open-channel-token-gating-details + [name token-gating emoji channel-color] + (rf/dispatch + [:bottom-sheet/show-sheet + {:content + (fn [] + [channel-token-gating-details name token-gating emoji channel-color]) + :content-height 210}])) -(defn channel-list-component-fn - [channel-heights first-channel-height] - [rn/view - {:on-layout #(swap! first-channel-height - (fn [] - (+ (if platform/ios? - 0 - 38) - (int (Math/ceil (oops/oget % "nativeEvent.layout.y")))))) - :style {:margin-top 20 :flex 1}} - (map-indexed (fn [index category] - (let [first-category (first category)] - ^{:key first-category} - [rn/view - {:flex 1 - :key (str index first-category) - :on-layout #(swap! channel-heights - (fn [] - (sort-by :height - (conj @channel-heights - {:height (int (oops/oget % "nativeEvent.layout.y")) - :label first-category}))))} +(defn layout-y + [event] + (oops/oget event "nativeEvent.layout.y")) - [quo/divider-label - {:label first-category - :chevron-position :left}] - [rn/view - {:margin-left 8 - :margin-top 10 - :margin-bottom 8} - (map-indexed (fn [inner-index channel-data] - [rn/view - {:key (str inner-index (:name channel-data)) - :margin-top 4} - [quo/channel-list-item channel-data]]) - (first-category mock-list-of-channels))]])) - mock-list-of-channels)]) +(defn add-category-height + [categories-heights category height] + (swap! categories-heights + (fn [] + (sort-by :height + (conj @categories-heights + {:height height + :label category}))))) -(def channel-list-component (memoize channel-list-component-fn)) +(defn channel-list-component + [{:keys [on-categories-heights-changed + on-first-channel-height-changed]} + channels-list] + (let [categories-heights (reagent/atom [])] + [rn/view + {:on-layout #(on-first-channel-height-changed (+ (if platform/ios? + 0 + 38) + (int (Math/ceil (layout-y %))))) + :style {:margin-top 20 :flex 1}} + (map-indexed + (fn [index [category channels-for-category]] + [rn/view + {:flex 1 + :key (str index category) + :on-layout #(do + (add-category-height categories-heights category (int (layout-y %))) + (on-categories-heights-changed @categories-heights))} + + [quo/divider-label + {:label category + :chevron-position :left}] + [rn/view + {:margin-left 8 + :margin-top 10 + :margin-bottom 8} + (map (fn [channel] + [rn/view + {:key (:id channel) + :margin-top 4} + [quo/channel-list-item channel]]) + channels-for-category)]]) + channels-list)])) (defn request-to-join-text [is-open?] @@ -219,126 +149,167 @@ (i18n/label :t/joined) (i18n/label :t/pending))}]) -(defn render-page-content - [{:keys [name description locked joined images - status tokens tags requested-to-join-at] - :as community} - channel-heights first-channel-height] - (let [pending? (pos? requested-to-join-at) - thumbnail-image (get-in images [:thumbnail])] - (fn [] - [rn/view - [rn/view {:padding-horizontal 20} - (when (and (not joined) - (not pending?) - (= status :gated)) - [rn/view - {:position :absolute - :top 8 - :right 8} - [quo/permission-tag-container - {:locked locked - :status status - :tokens tokens - :on-press #(rf/dispatch - [:bottom-sheet/show-sheet - {:content-height 210 - :content - (fn [] - [quo/token-gating - {:community {:name name - :community-color colors/primary-50 - :community-avatar thumbnail-image - :gates {:join [{:token "KNC" - :token-img-src knc-token-img - :amount 200 - :is-sufficient? true} - {:token "MANA" - :token-img-src mana-token-img - :amount 10 - :is-sufficient? false - :is-purchasable true} - {:token "RARE" - :token-img-src rare-token-img - :amount 10 - :is-sufficient? - false}]}}}])}])}]]) - (when (or pending? joined) - [rn/view - {:position :absolute - :top 12 - :right 12} - [get-tag joined]]) - [rn/view {:margin-top 56} - [quo/text - {:accessibility-label :chat-name-text - :number-of-lines 1 - :ellipsize-mode :tail - :weight :semi-bold - :size :heading-1} name]] - [quo/text - {:accessibility-label :community-description-text - :number-of-lines 2 - :ellipsize-mode :tail - :weight :regular - :size :paragraph-1 - :style {:margin-top 8 :margin-bottom 12}} - description] - [quo/community-stats-column :card-view] - [rn/view {:margin-top 12}] - [quo/community-tags tags] - [preview-user-list] - [join-community community]] - [channel-list-component channel-heights first-channel-height]]))) +(defn community-token-gating-details + [name thumbnail-image tokens] + [rn/view {:height 200 :margin-top 20} + [quo/token-gating + {:community {:name name + :community-color colors/primary-50 + :community-avatar-img-src thumbnail-image + :gates tokens}}]]) -(defn render-sticky-header - [channel-heights first-channel-height] - (fn [scroll-height] - (when (> scroll-height @first-channel-height) +(defn add-on-press-handler + [community-id {:keys [name emoji id locked? token-gating] :or {locked? false} :as chat}] + (merge + chat + (if (and locked? token-gating) + {:on-press #(open-channel-token-gating-details + name + token-gating + emoji + (colors/custom-color :pink 50))} + + (when (and (not locked?) id) + {:on-press (fn [] + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch [:chat/navigate-to-chat (str community-id id)]) + (rf/dispatch [:search/home-filter-changed nil]))})))) + +(defn add-on-press-handler-to-chats + [community-id chats] + (mapv (partial add-on-press-handler community-id) chats)) + +(defn add-on-press-handler-to-categorized-chats + [community-id categorized-chats] + (reduce-kv (fn [acc category chats] + (assoc acc category (add-on-press-handler-to-chats community-id chats))) + {} + categorized-chats)) + +(defn community-header + [name] + [quo/text + {:accessibility-label :chat-name-text + :number-of-lines 1 + :ellipsize-mode :tail + :weight :semi-bold + :size :heading-1} + name]) + +(defn community-description + [description] + [quo/text + {:accessibility-label :community-description-text + :number-of-lines 2 + :ellipsize-mode :tail + :weight :regular + :size :paragraph-1 + :style {:margin-top 8 :margin-bottom 12}} + description]) + +(defn community-content + [{:keys [name description locked joined images + status tokens tags requested-to-join-at id] + :as community} + {:keys [on-categories-heights-changed + on-first-channel-height-changed]}] + (let [pending? (pos? requested-to-join-at) + thumbnail-image (get-in images [:thumbnail]) + chats-by-category (rf/sub [:communities/categorized-channels id]) + users (rf/sub [:communities/users id])] + [rn/view + [rn/view {:padding-horizontal 20} + (when (and (not joined) + (not pending?) + (= status :gated)) + [rn/view + {:position :absolute + :top 8 + :right 8} + [quo/permission-tag-container + {:locked locked + :status status + :tokens tokens + :on-press #(rf/dispatch + [:bottom-sheet/show-sheet + {:content-height 210 + :content + (fn [] + [community-token-gating-details + name + thumbnail-image + tokens])}])}]]) + (when (or pending? joined) + [rn/view + {:position :absolute + :top 12 + :right 12} + [get-tag joined]]) + [rn/view {:margin-top 56} + [community-header name]] + [community-description description] + [quo/community-stats-column :card-view] + [rn/view {:margin-top 12}] + [quo/community-tags tags] + [preview-user-list users] + [join-community community]] + [channel-list-component + {:on-categories-heights-changed #(on-categories-heights-changed %) + :on-first-channel-height-changed #(on-first-channel-height-changed %)} + (add-on-press-handler-to-categorized-chats id chats-by-category)]])) + +(defn sticky-category-header + [_] + (fn [{:keys [:enabled :label]}] + (when enabled [blur/view {:blur-amount 32 :blur-type :xlight :overlay-color (if platform/ios? colors/white-opa-70 :transparent) :style style/blur-channel-header} [quo/divider-label - {:label (:label (last (filter (fn [{:keys [height]}] - (>= scroll-height (+ height @first-channel-height))) - @channel-heights))) + {:label (:label label) :chevron-position :left}]]))) +(defn community-overview-right-section-buttons + [id] + [{:icon :i/options + :background-color (scroll-page/icon-color) + :on-press #(rf/dispatch + [:bottom-sheet/show-sheet + {:content + (fn [] + [options/community-options-bottom-sheet + id])}])}]) + (defn community-card-page-view - [{:keys [name images id] :as community}] - (let [channel-heights (reagent/atom []) + [{:keys [name images id]}] + (let [categories-heights (reagent/atom []) first-channel-height (reagent/atom 0) - scroll-component (scroll-page/scroll-page - {:uri (get-in images [:large :uri])} - {:right-section-buttons [{:icon :i/options - :background-color (scroll-page/icon-color) - :on-press - #(rf/dispatch - [:bottom-sheet/show-sheet - {:content - (fn [] - [options/community-options-bottom-sheet - id])}])}]} - name)] - (fn [] - (let [page-component (memoize (render-page-content community channel-heights first-channel-height)) - sticky-header (memoize (render-sticky-header channel-heights first-channel-height))] - (fn [] - (scroll-component - sticky-header - page-component)))))) + scroll-height (reagent/atom 0) + cover {:uri (get-in images [:large :uri])}] + (fn [community] + [scroll-page/scroll-page + {:cover-image cover + :page-nav-right-section-buttons (community-overview-right-section-buttons id) + :name name + :on-scroll #(reset! scroll-height %)} + + [sticky-category-header + {:enabled (> @scroll-height @first-channel-height) + :label (last (filter (fn [{:keys [height]}] + (>= @scroll-height (+ height @first-channel-height))) + @categories-heights))}] + [community-content + community + {:on-categories-heights-changed #(reset! categories-heights %) + :on-first-channel-height-changed #(reset! first-channel-height %)}]]))) (defn overview [] (let [id (rf/sub [:get-screen-params :community-overview]) community (rf/sub [:communities/community id])] [rn/view - {:style - {:position :absolute - :top (if platform/ios? 0 44) - :width "100%" - :height "110%"}} + {:style style/community-overview-container} [community-card-page-view community]])) diff --git a/src/status_im2/subs/communities.cljs b/src/status_im2/subs/communities.cljs index 5b2abf806f..fb9b666801 100644 --- a/src/status_im2/subs/communities.cljs +++ b/src/status_im2/subs/communities.cljs @@ -3,7 +3,8 @@ [re-frame.core :as re-frame] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils] - [status-im2.constants :as constants])) + [status-im2.constants :as constants] + [utils.i18n :as i18n])) (re-frame/reg-sub :communities @@ -214,3 +215,30 @@ (map #(assoc (get % 1) :community-id id)) (sort-by :position) (into [])))) + +(re-frame/reg-sub + :communities/categorized-channels + (fn [[_ community-id]] + [(re-frame/subscribe [:communities/community community-id])]) + (fn [[{:keys [joined categories chats]}] [_ _]] + (reduce + (fn [acc [_ {:keys [name categoryID id emoji can-post?]}]] + (let [category (keyword (get-in categories [categoryID :name] (i18n/label :t/none)))] + (update acc + category + #(vec (conj %1 %2)) + {:name name + :emoji emoji + :locked? (or (not joined) (not can-post?)) + :id id}))) + {} + chats))) + +(re-frame/reg-sub + :communities/users + :<- [:communities] + (fn [_ [_ _]] + [{:full-name "Alicia K"} + {:full-name "Marcus C"} + {:full-name "MNO PQR"} + {:full-name "STU VWX"}])) diff --git a/src/status_im2/subs/communities_test.cljs b/src/status_im2/subs/communities_test.cljs index 6577ca68c7..885827dadf 100644 --- a/src/status_im2/subs/communities_test.cljs +++ b/src/status_im2/subs/communities_test.cljs @@ -3,7 +3,8 @@ [re-frame.db :as rf-db] [test-helpers.unit :as h] status-im2.subs.communities - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.i18n :as i18n])) (use-fixtures :each {:before #(reset! rf-db/app-db {:communities/enabled? true})}) @@ -135,3 +136,36 @@ {:id "0x1" :name "Civilized monkeys"} {:id "0x2" :name "Civilized rats"}] (rf/sub [sub-name]))))) + +(h/deftest-sub :communities/categorized-channels + [sub-name] + (testing "Channels with categories" + (swap! rf-db/app-db assoc + :communities/enabled? true + :communities + {"0x1" {:id "0x1" + :chats {"0x1" {:id "0x1" :name "chat1" :categoryID 1 :can-post? true} + "0x2" {:id "0x1" :name "chat2" :categoryID 1 :can-post? false} + "0x3" {:id "0x1" :name "chat3" :categoryID 2 :can-post? true}} + :categories {1 {:id 1 :name "category1"} + 2 {:id 2 :name "category2"}} + :joined true}}) + (is (= {:category1 [{:name "chat1" :emoji nil :locked? false :id "0x1"} + {:name "chat2" :emoji nil :locked? true :id "0x1"}] + :category2 [{:name "chat3" :emoji nil :locked? false :id "0x1"}]} + (rf/sub [sub-name "0x1"])))) + (testing "Channels without categories" + (swap! rf-db/app-db assoc + :communities/enabled? true + :communities + {"0x1" {:id "0x1" + :chats {"0x1" {:id "0x1" :name "chat1" :categoryID 1 :can-post? true} + "0x2" {:id "0x1" :name "chat2" :categoryID 1 :can-post? false} + "0x3" {:id "0x1" :name "chat3" :can-post? true}} + :categories {1 {:id 1 :name "category1"} + 2 {:id 2 :name "category2"}} + :joined true}}) + (is (= {:category1 [{:name "chat1" :emoji nil :locked? false :id "0x1"} + {:name "chat2" :emoji nil :locked? true :id "0x1"}] + (keyword (i18n/label :t/none)) [{:name "chat3" :emoji nil :locked? false :id "0x1"}]} + (rf/sub [sub-name "0x1"]))))) diff --git a/translations/en.json b/translations/en.json index 516c90f625..ba19feceaf 100644 --- a/translations/en.json +++ b/translations/en.json @@ -213,7 +213,7 @@ "membership-title": "Membership requirement", "create-channel-title": "New channel", "edit-channel-title": "Edit channel", - "community-admins-will-review-your-request":"Community admins will review your request", + "community-admins-will-review-your-request": "Community admins will review your request", "community-thumbnail-image": "Thumbnail image", "community-emoji-thumbnail-title": "Thumbnail", "community-thumbnail-upload": "Upload", @@ -1943,5 +1943,8 @@ "contact-request-chat-pending": "Your contact request is pending", "contact-request-chat-add": "Add {{name}} to send a message", "join-request": "Join request", + "join-one-user": "Join {{user}}", + "join-two-users": "Join {{user1}} and {{user2}}", + "join-more-users": "Join {{user1}}, {{user2}} and {{left-count}} more", "wants-to-join": "wants to join" }