Group Details Screen (2) (#14427)

* feat: group details screen (2)
This commit is contained in:
Omar Basem 2022-11-29 10:41:19 +04:00 committed by GitHub
parent 9e1412007f
commit 49e9738ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 355 additions and 172 deletions

View File

@ -151,3 +151,8 @@
:mutual-contact-enabled? :mutual-contact-enabled?
enabled? enabled?
nil)) nil))
(fx/defn set-search-query
{:events [:contacts/set-search-query]}
[{:keys [db] :as cofx} value]
{:db (assoc db :contacts/search-query value)})

View File

@ -21,89 +21,89 @@
{:events [:chat-removed]} {:events [:chat-removed]}
[cofx response] [cofx response]
(fx/merge cofx (fx/merge cofx
{:db (dissoc (:db cofx) :current-chat-id) {:db (dissoc (:db cofx) :current-chat-id)
:dispatch-n [[:sanitize-messages-and-process-response response] :dispatch-n [[:sanitize-messages-and-process-response response]
[:pop-to-root-tab :chat-stack]]} [:pop-to-root-tab :chat-stack]]}
(notification-center/get-activity-center-notifications-count))) (notification-center/get-activity-center-notifications-count)))
(fx/defn handle-chat-update (fx/defn handle-chat-update
{:events [:chat-updated]} {:events [:chat-updated]}
[_ response] [_ response do-not-navigate?]
{:dispatch-n [[:sanitize-messages-and-process-response response] {:dispatch-n [[:sanitize-messages-and-process-response response]
[:navigate-chat-updated (.-id (aget (.-chats response) 0))]]}) (when-not do-not-navigate? [:navigate-chat-updated (.-id (aget (.-chats response) 0))])]})
(fx/defn remove-member (fx/defn remove-member
"Format group update message and sign membership" "Format group update message and sign membership"
{:events [:group-chats.ui/remove-member-pressed]} {:events [:group-chats.ui/remove-member-pressed]}
[_ chat-id member] [_ chat-id member do-not-navigate?]
{::json-rpc/call [{:method "wakuext_removeMemberFromGroupChat" {::json-rpc/call [{:method "wakuext_removeMemberFromGroupChat"
:params [nil chat-id member] :params [nil chat-id member]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated % do-not-navigate?])}]})
(fx/defn join-chat (fx/defn join-chat
{:events [:group-chats.ui/join-pressed]} {:events [:group-chats.ui/join-pressed]}
[_ chat-id] [_ chat-id]
{::json-rpc/call [{:method "wakuext_confirmJoiningGroup" {::json-rpc/call [{:method "wakuext_confirmJoiningGroup"
:params [chat-id] :params [chat-id]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn create (fx/defn create
{:events [:group-chats.ui/create-pressed] {:events [:group-chats.ui/create-pressed]
:interceptors [(re-frame/inject-cofx :random-guid-generator)]} :interceptors [(re-frame/inject-cofx :random-guid-generator)]}
[{:keys [db] :as cofx} group-name] [{:keys [db] :as cofx} group-name]
(let [selected-contacts (:group/selected-contacts db)] (let [selected-contacts (:group/selected-contacts db)]
{::json-rpc/call [{:method "wakuext_createGroupChatWithMembers" {::json-rpc/call [{:method "wakuext_createGroupChatWithMembers"
:params [nil group-name (into [] selected-contacts)] :params [nil group-name (into [] selected-contacts)]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn create-from-link (fx/defn create-from-link
[cofx {:keys [chat-id invitation-admin chat-name]}] [cofx {:keys [chat-id invitation-admin chat-name]}]
(if (get-in cofx [:db :chats chat-id]) (if (get-in cofx [:db :chats chat-id])
{:dispatch-n [[:accept-all-activity-center-notifications-from-chat chat-id] {:dispatch-n [[:accept-all-activity-center-notifications-from-chat chat-id]
[:chat.ui/navigate-to-chat chat-id]]} [:chat.ui/navigate-to-chat chat-id]]}
{::json-rpc/call [{:method "wakuext_createGroupChatFromInvitation" {::json-rpc/call [{:method "wakuext_createGroupChatFromInvitation"
:params [chat-name chat-id invitation-admin] :params [chat-name chat-id invitation-admin]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn make-admin (fx/defn make-admin
{:events [:group-chats.ui/make-admin-pressed]} {:events [:group-chats.ui/make-admin-pressed]}
[_ chat-id member] [_ chat-id member]
{::json-rpc/call [{:method "wakuext_addAdminsToGroupChat" {::json-rpc/call [{:method "wakuext_addAdminsToGroupChat"
:params [nil chat-id [member]] :params [nil chat-id [member]]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn add-members (fx/defn add-members
"Add members to a group chat" "Add members to a group chat"
{:events [:group-chats.ui/add-members-pressed]} {:events [:group-chats.ui/add-members-pressed]}
[{{:keys [current-chat-id selected-participants]} :db :as cofx}] [{{:keys [current-chat-id selected-participants]} :db :as cofx}]
{::json-rpc/call [{:method "wakuext_addMembersToGroupChat" {::json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil current-chat-id selected-participants] :params [nil current-chat-id selected-participants]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn add-members-from-invitation (fx/defn add-members-from-invitation
"Add members to a group chat" "Add members to a group chat"
{:events [:group-chats.ui/add-members-from-invitation]} {:events [:group-chats.ui/add-members-from-invitation]}
[{{:keys [current-chat-id] :as db} :db :as cofx} id participant] [{{:keys [current-chat-id] :as db} :db :as cofx} id participant]
{:db (assoc-in db [:group-chat/invitations id :state] constants/invitation-state-approved) {:db (assoc-in db [:group-chat/invitations id :state] constants/invitation-state-approved)
::json-rpc/call [{:method "wakuext_addMembersToGroupChat" ::json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil current-chat-id [participant]] :params [nil current-chat-id [participant]]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn leave (fx/defn leave
"Leave chat" "Leave chat"
{:events [:group-chats.ui/leave-chat-confirmed]} {:events [:group-chats.ui/leave-chat-confirmed]}
[{:keys [db] :as cofx} chat-id] [{:keys [db] :as cofx} chat-id]
{::json-rpc/call [{:method "wakuext_leaveGroupChat" {::json-rpc/call [{:method "wakuext_leaveGroupChat"
:params [nil chat-id true] :params [nil chat-id true]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-removed %])}]}) :on-success #(re-frame/dispatch [:chat-removed %])}]})
(fx/defn remove (fx/defn remove
"Remove chat" "Remove chat"
@ -125,10 +125,10 @@
[{:keys [db] :as cofx} chat-id new-name] [{:keys [db] :as cofx} chat-id new-name]
(when (valid-name? new-name) (when (valid-name? new-name)
{:db (assoc-in db [:chats chat-id :name] new-name) {:db (assoc-in db [:chats chat-id :name] new-name)
::json-rpc/call [{:method "wakuext_changeGroupChatName" ::json-rpc/call [{:method "wakuext_changeGroupChatName"
:params [nil chat-id new-name] :params [nil chat-id new-name]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn membership-retry (fx/defn membership-retry
{:events [:group-chats.ui/membership-retry]} {:events [:group-chats.ui/membership-retry]}
@ -147,19 +147,19 @@
(let [{:keys [invitation-admin]} (get chats current-chat-id) (let [{:keys [invitation-admin]} (get chats current-chat-id)
message (get-in db [:chat/memberships current-chat-id :message])] message (get-in db [:chat/memberships current-chat-id :message])]
{:db (assoc-in db [:chat/memberships current-chat-id] nil) {:db (assoc-in db [:chat/memberships current-chat-id] nil)
::json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest" ::json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest"
:params [nil current-chat-id invitation-admin message] :params [nil current-chat-id invitation-admin message]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})) :on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}))
(fx/defn send-group-chat-membership-rejection (fx/defn send-group-chat-membership-rejection
"Send group chat membership rejection" "Send group chat membership rejection"
{:events [:send-group-chat-membership-rejection]} {:events [:send-group-chat-membership-rejection]}
[cofx invitation-id] [cofx invitation-id]
{::json-rpc/call [{:method "wakuext_sendGroupChatInvitationRejection" {::json-rpc/call [{:method "wakuext_sendGroupChatInvitationRejection"
:params [nil invitation-id] :params [nil invitation-id]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}) :on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
(fx/defn handle-invitations (fx/defn handle-invitations
[{db :db} invitations] [{db :db} invitations]

View File

@ -77,7 +77,7 @@
(defn pin-indicator-container [] (defn pin-indicator-container []
{:margin-top 4 {:margin-top 4
:margin-left 68 :margin-left 54
:top 4 :top 4
:justify-content :center :justify-content :center
:align-self :flex-start :align-self :flex-start

View File

@ -18,3 +18,23 @@
:height 16 :height 16
:border-radius 6 :border-radius 6
:background-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5)}) :background-color (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5)})
(defn close-icon []
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:margin-left 20
:width 32
:height 32
:border-radius 10
:justify-content :center
:align-items :center
:margin-bottom 24})
(def bottom-container
{:position :absolute
:padding-horizontal 20
:padding-vertical 12
:padding-bottom 33
:width "100%"
:background-color colors/white
:flex-direction :row
:bottom 0})

View File

@ -5,24 +5,40 @@
[quo2.core :as quo2] [quo2.core :as quo2]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[i18n.i18n :as i18n] [i18n.i18n :as i18n]
[status-im2.common.contact-list-item.view :as contact-item])) [status-im.chat.models :as chat.models]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im.ui2.screens.chat.messages.message :as message]
[quo.components.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.common.home.actions.view :as actions]
[status-im.ui2.screens.common.contact-list.view :as contact-list]
[oops.core :refer [oget]]))
(defn back-button [] (defn back-button []
[quo2/button {:type :grey [quo2/button {:type :grey
:size 32 :size 32
:width 32
:style {:margin-left 20} :style {:margin-left 20}
:accessibility-label :back-button :accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back]) :on-press #(rf/dispatch [:navigate-back])}
:icon true} [quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
:i/arrow-left])
(defn options-button [] (defn options-button []
[quo2/button {:type :grey (let [group (rf/sub [:chats/current-chat])]
:size 32 [quo2/button {:type :grey
:style {:margin-right 20} :size 32
:accessibility-label :options-button :width 32
:icon true} :style {:margin-right 20}
:i/options]) :accessibility-label :options-button
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/group-details-actions group])}])}
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]]))
(defn top-buttons []
[rn/view {:style {:flex-direction :row
:padding-horizontal 20
:justify-content :space-between}}
[back-button] [options-button]])
(defn count-container [count] (defn count-container [count]
[rn/view {:style (style/count-container)} [rn/view {:style (style/count-container)}
@ -30,35 +46,58 @@
:weight :medium :weight :medium
:style {:text-align :center}} count]]) :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]}] (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}} [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 [quo2/text {:size :paragraph-2
:weight :medium :weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]]) :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]])
(def added (reagent/atom ()))
(defn contact-requests-sheet [group]
(let [added (reagent/atom ())]
(fn []
[:f>
(fn []
(let [{window-height :height} (rn/use-window-dimensions)
safe-area (safe-area/use-safe-area)]
[rn/view {:style {:height (- window-height (:top safe-area))}}
[rn/touchable-opacity
{:on-press #(rf/dispatch [:bottom-sheet/hide])
:style (style/close-icon)}
[quo2/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[quo2/text {:size :heading-1
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label :t/add-members)]
[rn/text-input {:placeholder (str (i18n/label :t/search) "...")
:style {:height 32
:padding-horizontal 20
:margin-vertical 12}
:on-change (fn [e] (rf/dispatch [:contacts/set-search-query (oget e "nativeEvent.text")]))}]
[contact-list/contact-list {:icon :check
:group group
:added added
:search? true}]
[rn/view {:style style/bottom-container}
[quo2/button {:style {:flex 1}
:on-press #(rf/dispatch [:bottom-sheet/hide])
:disabled (zero? (count @added))}
(i18n/label :t/save)]]]))])))
(defn group-details [] (defn group-details []
(let [{:keys [admins chat-id chat-name color public?]} (rf/sub [:chats/current-chat]) (let [{:keys [admins chat-id chat-name color public? muted contacts] :as group} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/current-chat-contacts]) members (rf/sub [:contacts/group-members-sections])
sectioned-members (prepare-members members)
pinned-messages (rf/sub [:chats/pinned chat-id]) pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key]) current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)] admin? (get admins current-pk)]
[rn/view {:style {:flex 1 [rn/view {:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}} :background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header {:left-component [back-button] [quo2/header {:left-component [back-button]
:right-component [options-button] :right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}] :background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view {:style {:flex-direction :row [rn/view {:style {:flex-direction :row
:margin-top 12 :margin-top 24
:padding-horizontal 20}} :padding-horizontal 20}}
[quo2/group-avatar {:color color [quo2/group-avatar {:color color
:size :medium}] :size :medium}]
@ -68,23 +107,33 @@
[rn/view {:style {:margin-top 8}} [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)}]]] [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/view {:style (style/actions-view)}
[rn/touchable-opacity {:style (style/action-container color)} [rn/touchable-opacity {:style (style/action-container color)
:on-press (fn []
(rf/dispatch [:bottom-sheet/show-sheet
{:content #(message/pinned-messages-list chat-id)}]))}
[rn/view {:style {:flex-direction :row [rn/view {:style {:flex-direction :row
:justify-content :space-between}} :justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] [quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages)]] [count-container (count pinned-messages)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/pinned-messages-2)]] [quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/pinned-messages)]]
[rn/touchable-opacity {:style (style/action-container color)} [rn/touchable-opacity {:style (style/action-container color)
[quo2/icon :i/activity-center {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] :on-press #(rf/dispatch [::chat.models/mute-chat-toggled chat-id (not muted)])}
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/mute-group)]] [quo2/icon (if muted :i/muted :i/activity-center) {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[rn/touchable-opacity {:style (style/action-container color)} [quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity {:style (style/action-container color)
:on-press #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn [] [contact-requests-sheet group])}])}
[rn/view {:style {:flex-direction :row [rn/view {:style {:flex-direction :row
:justify-content :space-between}} :justify-content :space-between}}
[quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}] [quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count members)]] [count-container (count contacts)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if admin? :t/manage-members :t/add-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 [rn/section-list {:key-fn :title
:sticky-section-headers-enabled false :sticky-section-headers-enabled false
:sections sectioned-members :sections members
:render-section-header-fn contacts-section-header :render-section-header-fn contacts-section-header
:render-fn contact-item/contact-item}]])) :render-fn contact-list-item/contact-list-item
:render-data {:chat-id chat-id
:admin? admin?
:icon :options}}]]))

View File

@ -41,7 +41,8 @@
[quo2.components.avatars.user-avatar :as user-avatar] [quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.markdown.text :as text] [quo2.components.markdown.text :as text]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im2.contexts.chat.home.chat-list-item.view :as home.chat-list-item]) [status-im2.contexts.chat.home.chat-list-item.view :as home.chat-list-item]
[quo2.core :as quo2])
(:require-macros [status-im.utils.views :refer [defview letsubs]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defview mention-element [from] (defview mention-element [from]
@ -774,8 +775,9 @@
current-chat (rf/sub [:chats/current-chat]) current-chat (rf/sub [:chats/current-chat])
community (rf/sub [:communities/community (:community-id current-chat)])] community (rf/sub [:communities/community (:community-id current-chat)])]
[rn/view {:accessibility-label :pinned-messages-list} [rn/view {:accessibility-label :pinned-messages-list}
[rn/text {:style (merge typography/heading-1 typography/font-semi-bold {:margin-horizontal 20 [quo2/text {:size :heading-1
:color (colors/theme-colors colors/neutral-100 colors/white)})} :weight :semi-bold
:style {:margin-horizontal 20}}
(i18n/label :t/pinned-messages)] (i18n/label :t/pinned-messages)]
(when community (when community
[rn/view {:style {:flex-direction :row [rn/view {:style {:flex-direction :row
@ -804,15 +806,16 @@
:separator [rn/view {:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80) :height 1 :margin-top 8}]}] :separator [rn/view {:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80) :height 1 :margin-top 8}]}]
[rn/view {:style {:justify-content :center [rn/view {:style {:justify-content :center
:align-items :center :align-items :center
:flex 1
:margin-top 20}} :margin-top 20}}
[rn/view {:style {:width 120 [rn/view {:style {:width 120
:height 120 :height 120
:justify-content :center :justify-content :center
:align-items :center :align-items :center
:border-width 1}} [icons/icon :i/placeholder]] :border-width 1}} [icons/icon :i/placeholder]]
[rn/text {:style (merge typography/paragraph-1 typography/font-semi-bold {:margin-top 20})} (i18n/label :t/no-pinned-messages)] [quo2/text {:weight :semi-bold
[rn/text {:style (merge typography/paragraph-2 typography/font-regular)} :style {:margin-top 20}}
(i18n/label :t/no-pinned-messages)]
[quo2/text {:size :paragraph-2}
(i18n/label (if community :t/no-pinned-messages-community-desc :t/no-pinned-messages-desc))]])])) (i18n/label (if community :t/no-pinned-messages-community-desc :t/no-pinned-messages-desc))]])]))
(defn pin-system-message [{:keys [from in-popover? timestamp-str chat-id] :as message} {:keys [modal close-modal]}] (defn pin-system-message [{:keys [from in-popover? timestamp-str chat-id] :as message} {:keys [modal close-modal]}]

View File

@ -0,0 +1,19 @@
(ns status-im.ui2.screens.common.contact-list.view
(:require [react-native.core :as rn]
[status-im2.common.contact-list-item.view :as contact-list-item]
[utils.re-frame :as rf]
[quo2.core :as quo]))
(defn contacts-section-header [{:keys [title]}]
[quo/divider-label {:label title}])
(defn contact-list [data]
(let [contacts (rf/sub [:contacts/filtered-active-sections])]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections contacts
:render-section-header-fn contacts-section-header
:content-container-style {:padding-bottom 120}
:render-data data
:render-fn contact-list-item/contact-list-item}]))

View File

@ -1,28 +1,47 @@
(ns status-im2.common.contact-list-item.view (ns status-im2.common.contact-list-item.view
(:require [utils.re-frame :as rf] (:require [quo2.foundations.colors :as colors]
[react-native.core :as rn] [status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.re-frame :as rf]
[status-im2.common.home.actions.view :as actions]
[quo2.core :as quo] [quo2.core :as quo]
[quo2.foundations.colors :as colors] [react-native.core :as rn]
[status-im2.common.contact-list-item.style :as style] [react-native.platform :as platform]
[utils.address :as utils.address] [utils.address :as utils.address]))
[status-im2.common.home.actions.view :as actions]))
(defn open-chat [chat-id] (defn open-chat [chat-id]
(rf/dispatch [:dismiss-keyboard]) (let [view-id (rf/sub [:view-id])]
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id]) (when (= view-id :shell-stack)
(rf/dispatch [:search/home-filter-changed nil]) (rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id])) (if platform/android?
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))
(rf/dispatch [:search/home-filter-changed nil])
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))))
(defn contact-item [item] (defn action-icon [{:keys [public-key] :as item} {:keys [icon group added] :as extra-data}]
(let [{:keys [contacts]} group
member? (contains? contacts public-key)]
[rn/touchable-opacity {:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item extra-data])}])
:style {:position :absolute
:right 20}}
(if (= icon :options)
[quo/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
[quo/checkbox {:default-checked? member?
:on-change (fn [selected] (if selected
(swap! added conj public-key)
(reset! added (remove #(= % public-key) @added))))}])]))
(defn contact-list-item [item _ _ extra-data]
(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])] 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) :active-opacity 1
:on-long-press #(when-not (= current-pk public-key) :on-press #(open-chat public-key)
(rf/dispatch [:bottom-sheet/show-sheet :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}]))}) {:content (fn [] [actions/actions item extra-data])}])})
[quo/user-avatar {:full-name display-name [quo/user-avatar {:full-name display-name
:profile-picture photo-path :profile-picture photo-path
:status-indicator? true :status-indicator? true
@ -38,12 +57,9 @@
(when added? (when added?
[rn/view {:style {:margin-left 5 :margin-top 4}} [rn/view {:style {:margin-left 5 :margin-top 4}}
[quo/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))] [quo/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
[quo/text {:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} [quo/text {:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(utils.address/get-shortened-address public-key)]] (utils.address/get-shortened-address public-key)]]
(when-not (= current-pk public-key) (when-not (= current-pk public-key)
[rn/touchable-opacity {:style {:position :absolute [action-icon item extra-data])]))
:right 20}
:active-opacity 1
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item])}])}
[quo/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]])]))

View File

@ -4,7 +4,7 @@
[quo2.components.drawers.action-drawers :as drawer] [quo2.components.drawers.action-drawers :as drawer]
[status-im2.common.confirmation-drawer.view :as confirmation-drawer] [status-im2.common.confirmation-drawer.view :as confirmation-drawer]
;;TODO move to status-im2 ;;TODO move to status-im2
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.chat.models :as chat.models] [status-im.chat.models :as chat.models]
[status-im.chat.models.pin-message :as models.pin-message])) [status-im.chat.models.pin-message :as models.pin-message]))
@ -46,45 +46,43 @@
(defn clear-history-action [{:keys [chat-id] :as item}] (defn clear-history-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet (hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn [] {:content (fn []
(confirmation-drawer/confirmation-drawer (confirmation-drawer/confirmation-drawer {:title (i18n/label :t/clear-history?)
{:title (i18n/label :t/clear-history?) :description (i18n/label :t/clear-history-confirmation-content)
:description (i18n/label :t/clear-history-confirmation-content) :context item
:context item :button-text (i18n/label :t/clear-history)
:button-text (i18n/label :t/clear-history) :on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
(defn delete-chat-action [{:keys [chat-id] :as item}] (defn delete-chat-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet (hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn [] {:content (fn []
(confirmation-drawer/confirmation-drawer (confirmation-drawer/confirmation-drawer {:title (i18n/label :t/delete-chat?)
{:title (i18n/label :t/delete-chat?) :description (i18n/label :t/delete-chat-confirmation)
:description (i18n/label :t/delete-chat-confirmation) :context item
:context item :button-text (i18n/label :t/delete-chat)
:button-text (i18n/label :t/delete-chat) :on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
(defn leave-group-action [{:keys [chat-id] :as item}] (defn leave-group-action [item chat-id]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet (hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn [] {:content (fn []
(confirmation-drawer/confirmation-drawer (confirmation-drawer/confirmation-drawer {:title (i18n/label :t/leave-group?)
{:title (i18n/label :t/leave-group?) :description (i18n/label :t/leave-chat-confirmation)
:description (i18n/label :t/leave-chat-confirmation) :context item
:context item :button-text (i18n/label :t/leave-group)
:button-text (i18n/label :t/leave-group) :on-press #(do
:on-press #(hide-sheet-and-dispatch [:chat.ui/leave-chat chat-id])}))}])) (rf/dispatch [:navigate-back])
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed chat-id]))}))}]))
(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 [] (confirmation-drawer/confirmation-drawer {:content (fn [] (confirmation-drawer/confirmation-drawer {:title (i18n/label :t/block-user?)
{:title (i18n/label :t/block-user?) :description (i18n/label :t/block-contact-details)
: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])}))}]))
(defn mute-chat-entry [chat-id] (defn mute-chat-entry [chat-id]
(let [muted? (rf/sub [:chats/muted chat-id])] (let [muted? (rf/sub [:chats/muted chat-id])]
(entry {:icon :i/muted (entry {:icon (if muted? :i/muted :i/activity-center)
:label (i18n/label :label (i18n/label
(if muted? (if muted?
:unmute-chat :unmute-chat
@ -122,13 +120,14 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
(defn leave-group-entry [item] (defn leave-group-entry [item extra-data]
(entry {:icon :i/log-out (entry {:icon :i/log-out
:label (i18n/label :t/leave-group) :label (i18n/label :t/leave-group)
:on-press #(leave-group-action item) :on-press #(leave-group-action item (if extra-data (:chat-id extra-data) (:chat-id item)))
:danger? true :danger? true
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false
:add-divider? extra-data}))
(defn view-profile-entry [chat-id] (defn view-profile-entry [chat-id]
(entry {:icon :i/friend (entry {:icon :i/friend
@ -146,14 +145,26 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
(defn notifications-entry [] ;; TODO(OmarBasem): Requires design input.
(entry {:icon :i/notifications (defn edit-name-image-entry []
:label (i18n/label :t/notifications) (entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented, requires design input") :on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false :danger? false
:sub-label "All messages" ; TODO: placeholder :sub-label nil
:chevron? true})) :chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn notifications-entry [add-divider?]
(entry {:icon :i/notifications
:label (i18n/label :t/notifications)
:on-press #(js/alert "TODO: to be implemented, requires design input")
:danger? false
:sub-label "All messages" ; TODO: placeholder
:chevron? true
:add-divider? add-divider?}))
;; TODO(OmarBasem): Requires design input.
(defn fetch-messages-entry [] (defn fetch-messages-entry []
(entry {:icon :i/save (entry {:icon :i/save
:label (i18n/label :t/fetch-messages) :label (i18n/label :t/fetch-messages)
@ -162,6 +173,7 @@
:sub-label nil :sub-label nil
:chevron? true})) :chevron? true}))
;; TODO(OmarBasem): Requires design input.
(defn pinned-messages-entry [] (defn pinned-messages-entry []
(entry {:icon :i/pin (entry {:icon :i/pin
:label (i18n/label :t/pinned-messages) :label (i18n/label :t/pinned-messages)
@ -178,6 +190,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn rename-entry [] (defn rename-entry []
(entry {:icon :i/edit (entry {:icon :i/edit
:label (i18n/label :t/rename) :label (i18n/label :t/rename)
@ -186,6 +199,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn show-qr-entry [] (defn show-qr-entry []
(entry {:icon :i/qr-code (entry {:icon :i/qr-code
:label (i18n/label :t/show-qr) :label (i18n/label :t/show-qr)
@ -194,6 +208,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-profile-entry [] (defn share-profile-entry []
(entry {:icon :i/share (entry {:icon :i/share
:label (i18n/label :t/share-profile) :label (i18n/label :t/share-profile)
@ -202,6 +217,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-group-entry [] (defn share-group-entry []
(entry {:icon :i/share (entry {:icon :i/share
:label (i18n/label :t/share) :label (i18n/label :t/share)
@ -210,6 +226,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): Requires status-go impl.
(defn mark-untrustworthy-entry [] (defn mark-untrustworthy-entry []
(entry {:icon :i/alert (entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy) :label (i18n/label :t/mark-untrustworthy)
@ -227,6 +244,16 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
(defn remove-from-group-entry [{:keys [public-key]} chat-id]
(let [username (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))]
(entry {:icon :i/placeholder
:label (i18n/label :t/remove-user-from-group {:username username})
:on-press #(hide-sheet-and-dispatch [:group-chats.ui/remove-member-pressed chat-id public-key true])
:danger? true
:sub-label nil
:chevron? false
:add-divider? true})))
(defn group-details-entry [chat-id] (defn group-details-entry [chat-id]
(entry {:icon :i/members (entry {:icon :i/members
:label (i18n/label :t/group-details) :label (i18n/label :t/group-details)
@ -235,6 +262,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn add-members-entry [] (defn add-members-entry []
(entry {:icon :i/add-user (entry {:icon :i/add-user
:label (i18n/label :t/add-members) :label (i18n/label :t/add-members)
@ -243,6 +271,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn manage-members-entry [] (defn manage-members-entry []
(entry {:icon :i/add-user (entry {:icon :i/add-user
:label (i18n/label :t/manage-members) :label (i18n/label :t/manage-members)
@ -251,6 +280,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn edit-group-entry [] (defn edit-group-entry []
(entry {:icon :i/edit (entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image) :label (i18n/label :t/edit-name-and-image)
@ -259,6 +289,7 @@
:sub-label nil :sub-label nil
:chevron? false})) :chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn group-privacy-entry [] (defn group-privacy-entry []
(entry {:icon :i/privacy (entry {:icon :i/privacy
:label (i18n/label :t/change-group-privacy) :label (i18n/label :t/change-group-privacy)
@ -270,13 +301,13 @@
(defn destructive-actions [{:keys [group-chat] :as item}] (defn destructive-actions [{:keys [group-chat] :as item}]
[(clear-history-entry item) [(clear-history-entry item)
(if group-chat (if group-chat
(leave-group-entry item) (leave-group-entry item nil)
(delete-chat-entry item))]) (delete-chat-entry item))])
(defn notification-actions [{:keys [chat-id group-chat public?]} inside-chat?] (defn notification-actions [{:keys [chat-id group-chat public?]} inside-chat?]
[(mark-as-read-entry chat-id) [(mark-as-read-entry chat-id)
(mute-chat-entry chat-id) (mute-chat-entry chat-id)
(notifications-entry) (notifications-entry false)
(if inside-chat? (if inside-chat?
(fetch-messages-entry) (fetch-messages-entry)
(pinned-messages-entry)) (pinned-messages-entry))
@ -288,8 +319,8 @@
(share-group-entry))]) (share-group-entry))])
(defn group-actions [{:keys [chat-id admins]} inside-chat?] (defn group-actions [{:keys [chat-id admins]} inside-chat?]
(let [current-pk (rf/sub [:multiaccount/public-key]) (let [current-pub-key (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)] admin? (get admins current-pub-key)]
[(group-details-entry chat-id) [(group-details-entry chat-id)
(when inside-chat? (when inside-chat?
(if admin? (if admin?
@ -316,17 +347,21 @@
(notification-actions item inside-chat?) (notification-actions item inside-chat?)
(destructive-actions item)]]) (destructive-actions item)]])
(defn contact-actions [{:keys [public-key added] :as contact}] (defn contact-actions [{:keys [public-key] :as contact} {:keys [chat-id admin?] :as extra-data}]
[drawer/action-drawer [[(view-profile-entry public-key) (let [current-pub-key (rf/sub [:multiaccount/public-key])]
(when added [drawer/action-drawer [[(view-profile-entry public-key)
(remove-from-contacts-entry contact) (remove-from-contacts-entry contact)
(rename-entry) (rename-entry)
(show-qr-entry) (show-qr-entry)
(share-profile-entry))] (share-profile-entry)]
[(mark-untrustworthy-entry) [(mark-untrustworthy-entry)
(block-user-entry contact)]]]) (block-user-entry contact)]
(when (and admin? chat-id)
[(if (= current-pub-key public-key)
(leave-group-entry contact extra-data)
(remove-from-group-entry contact chat-id))])]]))
(defn actions [{:keys [chat-type] :as item} inside-chat?] (defn actions [{:keys [chat-type] :as item} {:keys [inside-chat?] :as extra-data}]
(case chat-type (case chat-type
constants/one-to-one-chat-type constants/one-to-one-chat-type
[one-to-one-actions item inside-chat?] [one-to-one-actions item inside-chat?]
@ -334,4 +369,11 @@
[public-chat-actions item inside-chat?] [public-chat-actions item inside-chat?]
constants/private-group-chat-type constants/private-group-chat-type
[private-group-chat-actions item inside-chat?] [private-group-chat-actions item inside-chat?]
[contact-actions item])) [contact-actions item extra-data]))
(defn group-details-actions [{:keys [admins] :as group}]
(let [current-pub-key (rf/sub [:multiaccount/public-key])
admin? (get admins current-pub-key)]
[drawer/action-drawer [(when admin? [(edit-name-image-entry)])
[(notifications-entry admin?)]
(destructive-actions group)]]))

View File

@ -1,7 +1,7 @@
(ns status-im2.contexts.chat.home.chat-list-item.style (ns status-im2.contexts.chat.home.chat-list-item.style
(:require [quo2.foundations.colors :as colors])) (:require [quo2.foundations.colors :as colors]))
(def container (defn container []
{:margin-top 8 {:margin-top 8
:margin-horizontal 8 :margin-horizontal 8
:padding-vertical 8 :padding-vertical 8

View File

@ -108,7 +108,7 @@
display-name (if group-chat name (first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))) display-name (if group-chat name (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])))
contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id])) contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id]))
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path chat-id]))] photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path chat-id]))]
[rn/touchable-opacity (merge {:style style/container [rn/touchable-opacity (merge {:style (style/container)
:on-press (open-chat chat-id) :on-press (open-chat chat-id)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item false])}])}) {:content (fn [] [actions/actions item false])}])})

View File

@ -8,7 +8,7 @@
[status-im2.common.home.view :as common.home] [status-im2.common.home.view :as common.home]
[status-im2.contexts.chat.home.contact-request.view :as contact-request] [status-im2.contexts.chat.home.contact-request.view :as contact-request]
[status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item] [status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item]
[status-im2.common.contact-list-item.view :as contact-list-item])) [status-im.ui2.screens.common.contact-list.view :as contact-list]))
(defn get-item-layout [_ index] (defn get-item-layout [_ index]
#js {:length 64 :offset (* 64 index) :index index}) #js {:length 64 :offset (* 64 index) :index index})
@ -44,9 +44,6 @@
[quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)] [quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)]
[quo/text (i18n/label :t/blank-contacts-text)]]) [quo/text (i18n/label :t/blank-contacts-text)]])
(defn contacts-section-header [{:keys [title]}]
[quo/divider-label {:label title}])
(defn contacts [contact-requests] (defn contacts [contact-requests]
(let [items (rf/sub [:contacts/active-sections])] (let [items (rf/sub [:contacts/active-sections])]
(if (empty? items) (if (empty? items)
@ -54,12 +51,7 @@
[:<> [:<>
(when (pos? (count contact-requests)) (when (pos? (count contact-requests))
[contact-request/contact-requests contact-requests]) [contact-request/contact-requests contact-requests])
[rn/section-list [contact-list/contact-list {:icon :options}]])))
{:key-fn :title
:sticky-section-headers-enabled false
:sections items
:render-section-header-fn contacts-section-header
:render-fn contact-list-item/contact-item}]])))
(defn tabs [] (defn tabs []
(let [selected-tab (reagent/atom :recent)] (let [selected-tab (reagent/atom :recent)]

View File

@ -8,7 +8,7 @@
[status-im2.setup.config :as config] [status-im2.setup.config :as config]
[status-im2.setup.hot-reload :as reloader] [status-im2.setup.hot-reload :as reloader]
;; TODO (14/11/22 flexsurfer) move to status-im2 namespace ;; TODO (14/11/22 flexsurfer) move to status-im2 namespace
[status-im.ui.screens.popover.views :as popover] [status-im.ui.screens.popover.views :as popover]
[status-im.ui.screens.profile.visibility-status.views :as visibility-status-views] [status-im.ui.screens.profile.visibility-status.views :as visibility-status-views]
[status-im.ui.screens.bottom-sheets.views :as bottom-sheets] [status-im.ui.screens.bottom-sheets.views :as bottom-sheets]

View File

@ -3,10 +3,11 @@
[status-im.contact.db :as contact.db] [status-im.contact.db :as contact.db]
[status-im.utils.image-server :as image-server] [status-im.utils.image-server :as image-server]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils] [status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[clojure.string :as string]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.gfycat.core :as gfycat] [status-im.utils.gfycat.core :as gfycat]
[status-im.ethereum.core :as ethereum])) [status-im.ethereum.core :as ethereum]
[clojure.string :as string]
[i18n.i18n :as i18n]))
(re-frame/reg-sub (re-frame/reg-sub
::query-current-chat-contacts ::query-current-chat-contacts
@ -251,4 +252,35 @@
(assoc acc address contact) (assoc acc address contact)
acc)) acc))
{} {}
contacts))) contacts)))
(re-frame/reg-sub
:contacts/filtered-active-sections
:<- [:contacts/active-sections]
:<- [:contacts/search-query]
(fn [[contacts query]]
(if (empty? query)
contacts
(->> contacts
(map (fn [item]
(update item :data (fn [data]
(filter #(string/includes?
(string/lower-case (:alias %))
(string/lower-case query))
data)))))
(remove #(empty? (:data %)))))))
(re-frame/reg-sub
:contacts/group-members-sections
:<- [:contacts/current-chat-contacts]
(fn [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 (i18n/label :t/owner) :data admins})
(seq online) (assoc :online {:title (i18n/label :t/online) :data online})
(seq offline) (assoc :offline {:title (i18n/label :t/offline) :data offline}))))))

View File

@ -140,6 +140,7 @@
(reg-root-key-sub :contacts/new-identity :contacts/new-identity) (reg-root-key-sub :contacts/new-identity :contacts/new-identity)
(reg-root-key-sub :group/selected-contacts :group/selected-contacts) (reg-root-key-sub :group/selected-contacts :group/selected-contacts)
(reg-root-key-sub :contacts/blocked-set :contacts/blocked) (reg-root-key-sub :contacts/blocked-set :contacts/blocked)
(reg-root-key-sub :contacts/search-query :contacts/search-query)
;;wallet ;;wallet
(reg-root-key-sub :wallet :wallet) (reg-root-key-sub :wallet :wallet)

View File

@ -1870,5 +1870,9 @@
"italic": "Italic", "italic": "Italic",
"strikethrough": "Strikethrough", "strikethrough": "Strikethrough",
"add-text": "Add text", "add-text": "Add text",
"send": "Send" "send": "Send",
"unmute-group": "Unmute group",
"remove-user-from-group": "Remove {{username}} from the group",
"edit-name-image": "Edit name and image",
"owner": "Owner"
} }