Refactor mock data out of community page (#14799)

This commit is contained in:
Volodymyr Kozieiev 2023-01-25 11:35:10 +00:00 committed by GitHub
parent 4e8ebc6d85
commit 3e93e353db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 424 additions and 340 deletions

View File

@ -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)

View File

@ -28,11 +28,9 @@
(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)
y (reanimated/use-shared-value scroll-height)
translate-animation (reanimated/interpolate y
input-range
output-range
@ -42,11 +40,11 @@
threshold (if platform/ios? 30 170)]
(rn/use-effect
#(do
(reanimated/set-shared-value y @scroll-height)
(reanimated/set-shared-value y scroll-height)
(reanimated/set-shared-value opacity-animation
(reanimated/with-timing (if (>= @scroll-height threshold) 1 0)
(reanimated/with-timing (if (>= scroll-height threshold) 1 0)
(clj->js {:duration 300}))))
[@scroll-height])
[scroll-height])
[:<>
[reanimated/blur-view
{:blur-amount 32
@ -78,48 +76,52 @@
:left-section {:icon :i/close
:icon-background-color (icon-color)
:on-press #(rf/dispatch [:navigate-back])}}]
(when sticky-header [sticky-header @scroll-height])]]))])
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)
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)
(reanimated/set-shared-value y scroll-height)
js/undefined)
[@scroll-height])
[scroll-height])
[reanimated/view
{:style (style/display-picture-container animation)}
[rn/image
{:source cover
:style style/display-picture}]]))])
: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])]])))

View File

@ -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)

View File

@ -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 []

View File

@ -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})

View File

@ -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)}))))

View File

@ -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))))))

View File

@ -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 []
(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 (colors/custom-color :pink 50)
: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 {: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}]}}}])
:gates token-gating}}]])
(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}]))
(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 layout-y
[event]
(oops/oget event "nativeEvent.layout.y"))
(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
(defn add-category-height
[categories-heights category height]
(swap! categories-heights
(fn []
(sort-by :height
(conj @channel-heights
{:height (int (oops/oget % "nativeEvent.layout.y"))
:label first-category}))))}
(conj @categories-heights
{:height height
:label category})))))
(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 first-category
{:label category
:chevron-position :left}]
[rn/view
{:margin-left 8
:margin-top 10
:margin-bottom 8}
(map-indexed (fn [inner-index channel-data]
(map (fn [channel]
[rn/view
{:key (str inner-index (:name channel-data))
{:key (:id channel)
:margin-top 4}
[quo/channel-list-item channel-data]])
(first-category mock-list-of-channels))]]))
mock-list-of-channels)])
(def channel-list-component (memoize channel-list-component-fn))
[quo/channel-list-item channel]])
channels-for-category)]])
channels-list)]))
(defn request-to-join-text
[is-open?]
@ -219,14 +149,74 @@
(i18n/label :t/joined)
(i18n/label :t/pending))}])
(defn render-page-content
(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 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]
status tokens tags requested-to-join-at id]
:as community}
channel-heights first-channel-height]
{:keys [on-categories-heights-changed
on-first-channel-height-changed]}]
(let [pending? (pos? requested-to-join-at)
thumbnail-image (get-in images [:thumbnail])]
(fn []
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)
@ -245,24 +235,10 @@
{: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}]}}}])}])}]])
[community-token-gating-details
name
thumbnail-image
tokens])}])}]])
(when (or pending? joined)
[rn/view
{:position :absolute
@ -270,75 +246,70 @@
: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]
[community-header name]]
[community-description description]
[quo/community-stats-column :card-view]
[rn/view {:margin-top 12}]
[quo/community-tags tags]
[preview-user-list]
[preview-user-list users]
[join-community community]]
[channel-list-component channel-heights first-channel-height]])))
[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 render-sticky-header
[channel-heights first-channel-height]
(fn [scroll-height]
(when (> scroll-height @first-channel-height)
(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-card-page-view
[{:keys [name images id] :as community}]
(let [channel-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
(defn community-overview-right-section-buttons
[id]
[{:icon :i/options
:background-color (scroll-page/icon-color)
:on-press
#(rf/dispatch
: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))))))
id])}])}])
(defn community-card-page-view
[{:keys [name images id]}]
(let [categories-heights (reagent/atom [])
first-channel-height (reagent/atom 0)
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]]))

View File

@ -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"}]))

View File

@ -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"])))))

View File

@ -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"
}