Group Details Screen (#14377)

* feat: group details screen
This commit is contained in:
Omar Basem 2022-11-21 16:03:49 +04:00 committed by GitHub
parent c08d58577d
commit 5492fb472f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 194 additions and 38 deletions

View File

@ -15,18 +15,12 @@
(defn group-avatar [_] (defn group-avatar [_]
(fn [{:keys [color size]}] (fn [{:keys [color size]}]
(let [container-size (get-in sizes [:container size]) (let [container-size (get-in sizes [:container size])
icon-size (get-in sizes [:icon size]) icon-size (get-in sizes [:icon size])]
;; theme (or override-theme (if (colors/dark?) :dark :light))
]
[rn/view {:width container-size [rn/view {:width container-size
:height container-size :height container-size
:align-items :center :align-items :center
:justify-content :center :justify-content :center
:border-radius (/ container-size 2) :border-radius (/ container-size 2)
:background-color color :background-color (colors/theme-alpha color 0.5 0.6)}
;; :background-color (if (= theme :light) TODO: colors/custom-color method here is not working for some reason.
;; (colors/custom-color color 50)
;; (colors/custom-color color 60))
}
[icon/icon :i/group {:size icon-size ; TODO: group icon sizes 12 and 20 (small and large) are missing [icon/icon :i/group {:size icon-size ; TODO: group icon sizes 12 and 20 (small and large) are missing
:color colors/white-opa-70}]]))) :color colors/white-opa-70}]])))

View File

@ -1,7 +1,8 @@
(ns react-native.core (ns react-native.core
(:require [reagent.core :as reagent] (:require [reagent.core :as reagent]
["react-native" :as react-native] ["react-native" :as react-native]
[react-native.flat-list :as flat-list])) [react-native.flat-list :as flat-list]
[react-native.section-list :as section-list]))
(def app-state ^js (.-AppState ^js react-native)) (def app-state ^js (.-AppState ^js react-native))
@ -9,7 +10,7 @@
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native))) (def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native)))
(def image (reagent/adapt-react-class (.-Image ^js react-native))) (def image (reagent/adapt-react-class (.-Image ^js react-native)))
(def text (reagent/adapt-react-class (.-Text ^js react-native))) (def text (reagent/adapt-react-class (.-Text ^js react-native)))
(def text-input (reagent/adapt-react-class (.-TextInput ^js react-native))) (def text-input (reagent/adapt-react-class (.-TextInput ^js react-native)))
(def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity ^js react-native))) (def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity ^js react-native)))
(def touchable-highlight (reagent/adapt-react-class (.-TouchableHighlight ^js react-native))) (def touchable-highlight (reagent/adapt-react-class (.-TouchableHighlight ^js react-native)))
@ -17,6 +18,8 @@
(def flat-list flat-list/flat-list) (def flat-list flat-list/flat-list)
(def section-list section-list/section-list)
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js react-native))) (def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js react-native)))
(def modal (reagent/adapt-react-class (.-Modal ^js react-native))) (def modal (reagent/adapt-react-class (.-Modal ^js react-native)))

View File

@ -0,0 +1,40 @@
(ns react-native.section-list
(:require [reagent.core :as reagent]
[react-native.flat-list :as flat-list]
["react-native" :as react-native]))
(def section-list-class (reagent/adapt-react-class (.-SectionList react-native)))
(def memo-wrap-render-fn
(memoize
(fn [f render-data]
(fn [^js data]
(reagent/as-element [f (.-item data) (.-index data) (.-separators data) render-data])))))
(defn- wrap-render-section-header-fn [f]
(fn [^js data]
(let [^js section (.-section data)]
(reagent/as-element [f {:title (.-title section)
:data (.-data section)}]))))
(defn- wrap-per-section-render-fn [props]
(update
(if-let [f (:render-fn props)]
(assoc (dissoc props :render-fn :render-data) :renderItem (memo-wrap-render-fn f (:render-data props)))
props)
:data to-array))
(defn section-list
"A wrapper for SectionList.
To render something on empty sections, use renderSectionFooter and conditionaly
render on empty data
See https://facebook.github.io/react-native/docs/sectionlist.html"
[{:keys [sections render-section-header-fn render-section-footer-fn style] :as props}]
[section-list-class
(merge (flat-list/base-list-props props)
props
(when render-section-footer-fn
{:renderSectionFooter (wrap-render-section-header-fn render-section-footer-fn)})
{:sections (clj->js (map wrap-per-section-render-fn sections))
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)
:style style})])

View File

@ -110,7 +110,7 @@
:blank-keycard-title :blank-keycard-title
:block :block
:block-contact :block-contact
:block-user-confirmation :block-contact-details
:blocked-users :blocked-users
:bootnode-address :bootnode-address
:bootnode-details :bootnode-details

View File

@ -12,7 +12,7 @@
in-progress? (reagent/atom false)] in-progress? (reagent/atom false)]
[react/view {:style {:padding-top 16 :padding-horizontal 24 :padding-bottom 8}} [react/view {:style {:padding-top 16 :padding-horizontal 24 :padding-bottom 8}}
[react/text {:style styles/sheet-text} [react/text {:style styles/sheet-text}
(i18n/label :t/block-user-confirmation)] (i18n/label :t/block-contact-details)]
[react/view {:align-items :center :margin-top 16} [react/view {:align-items :center :margin-top 16}
[quo/button {:theme :negative [quo/button {:theme :negative
:disabled @in-progress? :disabled @in-progress?

View File

@ -114,7 +114,8 @@
[status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto] [status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
[status-im.ui.screens.wallet.recipient.views :as recipient] [status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send] [status-im.ui.screens.wallet.send.views :as wallet.send]
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections])) [status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]
[status-im.ui2.screens.chat.group-details.view :as group-details]))
(defn right-button-options [id icon] (defn right-button-options [id icon]
{:id id {:id id
@ -211,10 +212,9 @@
:component pin-messages/pinned-messages} :component pin-messages/pinned-messages}
{:name :group-chat-profile {:name :group-chat-profile
:insets {:top false}
;;TODO animated-header ;;TODO animated-header
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component profile.group-chat/group-chat-profile} :component group-details/group-details}
{:name :group-chat-invite {:name :group-chat-invite
;;TODO parameter in the event ;;TODO parameter in the event
:options {:topBar {:visible false}} :options {:topBar {:visible false}}

View File

@ -72,7 +72,7 @@
(defn block-user-action [{:keys [public-key] :as item}] (defn block-user-action [{:keys [public-key] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet (hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn [] (common/alert {:title (i18n/label :t/block-user?) {:content (fn [] (common/alert {:title (i18n/label :t/block-user?)
:description (i18n/label :t/block-user-confirmation) :description (i18n/label :t/block-contact-details)
:context item :context item
:button-text (i18n/label :t/block-user) :button-text (i18n/label :t/block-user)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}])) :on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}]))
@ -262,8 +262,8 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
(defn destructive-actions [{:keys [chat-id group-chat] :as item}] (defn destructive-actions [{:keys [group-chat] :as item}]
[(clear-history-entry chat-id) [(clear-history-entry item)
(if group-chat (if group-chat
(leave-group-entry item) (leave-group-entry item)
(delete-chat-entry item))]) (delete-chat-entry item))])
@ -311,12 +311,13 @@
(notification-actions item inside-chat?) (notification-actions item inside-chat?)
(destructive-actions item)]]) (destructive-actions item)]])
(defn contact-actions [{:keys [public-key] :as contact}] (defn contact-actions [{:keys [public-key added] :as contact}]
[drawer/action-drawer [[(view-profile-entry public-key) [drawer/action-drawer [[(view-profile-entry public-key)
(remove-from-contacts-entry contact) (when added
(rename-entry) (remove-from-contacts-entry contact)
(show-qr-entry) (rename-entry)
(share-profile-entry)] (show-qr-entry)
(share-profile-entry))]
[(mark-untrustworthy-entry) [(mark-untrustworthy-entry)
(block-user-entry contact)]]]) (block-user-entry contact)]]])

View File

@ -22,11 +22,13 @@
(defn contact-item [item] (defn contact-item [item]
(let [{:keys [public-key ens-verified added? images]} item (let [{:keys [public-key ens-verified added? images]} item
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key])) display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))] photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))
current-pk (rf/sub [:multiaccount/public-key])]
[rn/touchable-opacity (merge {:style (style/container) [rn/touchable-opacity (merge {:style (style/container)
:on-press #(open-chat public-key) :on-press #(open-chat public-key)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet :on-long-press #(when-not (= current-pk public-key)
{:content (fn [] [actions/actions item])}])}) (rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}]))})
[user-avatar/user-avatar {:full-name display-name [user-avatar/user-avatar {:full-name display-name
:profile-picture photo-path :profile-picture photo-path
:status-indicator? true :status-indicator? true
@ -44,11 +46,14 @@
(when added? (when added?
[rn/view {:style {:margin-left 5 :margin-top 4}} [rn/view {:style {:margin-left 5 :margin-top 4}}
[icons/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))] [icons/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
[text/text {:size :paragraph-1 [text/text {:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(utils/get-shortened-address public-key)]] (utils/get-shortened-address public-key)]]
[rn/touchable-opacity {:style {:position :absolute (when-not (= current-pk public-key)
:right 20} [rn/touchable-opacity {:style {:position :absolute
:active-opacity 1} ; TODO: on-long-press to be added when contact bottom sheet is implemented :right 20}
[icons/icon :i/options {:size 20 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]])) :active-opacity 1
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}])}
[icons/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]])]))

View File

@ -0,0 +1,20 @@
(ns status-im.ui2.screens.chat.group-details.style
(:require [quo2.foundations.colors :as colors]))
(defn actions-view []
{:flex-direction :row
:justify-content :space-between
:margin-vertical 20
:padding-horizontal 20})
(defn action-container [color]
{:background-color (colors/theme-alpha color 0.1 0.1)
:flex 0.29
:border-radius 16
:padding 12})
(defn count-container []
{:width 16
:height 16
:border-radius 6
:background-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5)})

View File

@ -0,0 +1,90 @@
(ns status-im.ui2.screens.chat.group-details.view
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[status-im.ui2.screens.chat.group-details.style :as style]
[quo2.core :as quo2]
[utils.re-frame :as rf]
[i18n.i18n :as i18n]
[status-im.ui2.screens.chat.components.contact-item.view :as contact-item]))
(defn back-button []
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-left 20}
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn options-button []
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-right 20}
:accessibility-label :options-button}
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn count-container [count]
[rn/view {:style (style/count-container)}
[quo2/text {:size :label
:weight :medium
:style {:text-align :center}} count]])
(defn prepare-members [members]
(let [admins (filter :admin? members)
online (filter #(and (not (:admin? %)) (:online? %)) members)
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
(vals (cond-> {}
(seq admins) (assoc :owner {:title "Owner" :data admins})
(seq online) (assoc :online {:title "Online" :data online})
(seq offline) (assoc :offline {:title "Offline" :data offline})))))
(defn contacts-section-header [{:keys [title]}]
[rn/view {:style {:padding-horizontal 20 :border-top-width 1 :border-top-color colors/neutral-20 :padding-vertical 8 :margin-top 8}}
[quo2/text {:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]])
(defn group-details []
(let [{:keys [admins chat-id chat-name color public?]} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/current-chat-contacts])
sectioned-members (prepare-members members)
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view {:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header {:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view {:style {:flex-direction :row
:margin-top 12
:padding-horizontal 20}}
[quo2/group-avatar {:color color
:size :medium}]
[quo2/text {:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo2/icon (if public? :i/world :i/privacy) {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity {:style (style/action-container color)}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/pinned-messages-2)]]
[rn/touchable-opacity {:style (style/action-container color)}
[quo2/icon :i/activity-center {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/mute-group)]]
[rn/touchable-opacity {:style (style/action-container color)}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count members)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list {:key-fn :title
:sticky-section-headers-enabled false
:sections sectioned-members
:render-section-header-fn contacts-section-header
:render-fn contact-item/contact-item}]]))

View File

@ -21,7 +21,8 @@
[quo2.components.markdown.text :as quo2.text] [quo2.components.markdown.text :as quo2.text]
[status-im.qr-scanner.core :as qr-scanner] [status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles] [status-im.ui.components.chat-icon.styles :as chat-icon.styles]
[quo.react-native :as rn] [react-native.core :as rn]
[quo.react-native :as quo.rn]
[quo.react] [quo.react]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography] [quo2.foundations.typography :as typography]
@ -279,7 +280,7 @@
:render-fn messages-home-item}] :render-fn messages-home-item}]
[rn/view {:style {:flex 1}} (when (> (count requests) 0) [rn/view {:style {:flex 1}} (when (> (count requests) 0)
[contact-requests requests]) [contact-requests requests])
[list/section-list [rn/section-list
{:key-fn :title {:key-fn :title
:sticky-section-headers-enabled false :sticky-section-headers-enabled false
:sections contacts :sections contacts
@ -355,9 +356,9 @@
[:f> [:f>
(fn [] (fn []
(quo.react/effect! #(re-frame/dispatch [:get-activity-center-notifications])) (quo.react/effect! #(re-frame/dispatch [:get-activity-center-notifications]))
[rn/keyboard-avoiding-view {:style {:flex 1 [quo.rn/keyboard-avoiding-view {:style {:flex 1
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)} :background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
:ignore-offset true} :ignore-offset true}
[topbar/topbar {:navigation :none [topbar/topbar {:navigation :none
:use-insets true :use-insets true
:background (colors/theme-colors colors/neutral-5 colors/neutral-95) :background (colors/theme-colors colors/neutral-5 colors/neutral-95)

View File

@ -108,7 +108,7 @@
:blank-keycard-title :blank-keycard-title
:block :block
:block-contact :block-contact
:block-user-confirmation :block-contact-details
:blocked-users :blocked-users
:bootnode-address :bootnode-address
:bootnode-details :bootnode-details

View File

@ -90,7 +90,7 @@
"block": "Block", "block": "Block",
"unblock": "Unblock", "unblock": "Unblock",
"block-contact": "Block this user", "block-contact": "Block this user",
"block-user-confirmation": "Blocking will delete this user's previous messages and stop new ones from reaching you", "block-contact-details": "Blocking will delete this user's previous messages and stop new ones from reaching you",
"blocked-users": "Blocked users", "blocked-users": "Blocked users",
"bootnode-address": "Bootnode address", "bootnode-address": "Bootnode address",
"bootnode-details": "Bootnode details", "bootnode-details": "Bootnode details",
@ -1673,6 +1673,7 @@
"accept-and-continue": "Accept and continue", "accept-and-continue": "Accept and continue",
"empty-activity-center": "Your chat notifications\nwill appear here", "empty-activity-center": "Your chat notifications\nwill appear here",
"pinned-messages": "Pinned messages", "pinned-messages": "Pinned messages",
"pinned-messages-2": "Pinned \nmessages",
"pinned-a-message": "pinned a message", "pinned-a-message": "pinned a message",
"pin": "Pin", "pin": "Pin",
"unpin": "Unpin", "unpin": "Unpin",
@ -1856,6 +1857,7 @@
"edit-name-and-image": "Edit name and image", "edit-name-and-image": "Edit name and image",
"change-group-privacy": "Change group privacy", "change-group-privacy": "Change group privacy",
"manage-members": "Manage members", "manage-members": "Manage members",
"mute-group": "Mute group",
"delete-chat?": "Delete Chat?", "delete-chat?": "Delete Chat?",
"mark-user-untrustworthy": "Mark {{username}} as untrustworthy", "mark-user-untrustworthy": "Mark {{username}} as untrustworthy",
"leave-group?": "Leave Group?", "leave-group?": "Leave Group?",